{
  "openapi": "3.1.0",
  "info": {
    "title": "Kang Open Banking API",
    "version": "4.54.2",
    "summary": "Unified Open Banking API for Cameroon",
    "description": "Kang Open Banking (KOB) v1 API.\n\nProvides Account Information (AISP), Payment Initiation (PISP), Credit Scoring, Loans, Savings, Mobile Money, a double-entry Ledger, Virtual Card Issuing, Custodial Wallets, Escrow, Compliance Screening, SLA Monitoring, POS Commerce, Bank Directory, Bank Connector Kit, and an Interbank Engine (ISO 20022) for the CEMAC region. Monetary examples use XAF (Central African CFA Franc) unless stated otherwise.\n\nRegulatory status: this API is designed with COBAC and BEAC requirements in mind. KOB does not currently hold a COBAC or BEAC licence; licensing is in progress. No text on this surface should be interpreted as a claim of certification, accreditation, or regulatory approval.\n\nModule maturity: AISP and PISP are the production-track modules for v1. Loans, Savings, Virtual Card Issuing, Custodial Wallets, Escrow, Credit Scoring, the Ledger, and Interbank/ISO 20022 are exposed in sandbox for integration and pilot use and are not yet licensed for production traffic. Each tag carries an `x-maturity` value: `ga` (production-track: AISP, PISP, OAuth core, consents, monitoring, directory, specification), `preview` (sandbox and pilot; production use requires partner licensing and certification evidence) or `experimental` (partial).\n\nRate limits: Anonymous 60 requests/min, Sandbox API key 300 requests/min, Production Standard 1,200 requests/min; exceeding a limit returns 429 Problem Details with `Retry-After` and `X-RateLimit-*` headers. Every financial POST, PUT and PATCH accepts a UUID v4 `Idempotency-Key`.\n\nScheduled breaking changes: float money fields and the legacy Error envelope are removed in 5.0.0; the PublishableKey scheme is removed in 4.55.0. See /developer/changelog.\n\nAuthentication: the production-track surface uses OAuth 2.0 Authorization Code with PKCE and rotating refresh tokens. Some advanced flows (mTLS client auth, private_key_jwt, full FAPI 1.0 Advanced) are referenced in the specification but are not yet implemented end-to-end; they are tracked as Planned and must not be relied on for production integrations until separately announced.\n\nVersioning and changelog: per-release notes live at https://kangopenbanking.com/changelog.json and are also rendered at /developer/changelog. Internal release narration (engineering rationale, governance citations, per-cut self-review) is kept in an internal-only document and is not published on this surface.",
    "x-changelog-url": "https://kangopenbanking.com/changelog.json",
    "contact": {
      "name": "Kang Open Banking Support",
      "email": "support@kangopenbanking.com",
      "url": "https://kangopenbanking.com/contact"
    },
    "termsOfService": "https://kangopenbanking.com/terms",
    "license": {
      "name": "Proprietary",
      "url": "https://kangopenbanking.com/terms"
    },
    "x-sla-url": "https://kangopenbanking.com/sla",
    "x-status-page": "https://status.kangopenbanking.com",
    "x-uptime-sla": {
      "production": "99.9%",
      "sandbox": "99.5%",
      "incident_response": {
        "P1_critical": "30 minutes",
        "P2_high": "2 hours",
        "P3_medium": "8 hours",
        "P4_low": "48 hours"
      },
      "maintenance_notice": "72 hours advance notice"
    },
    "x-sdk-libraries": {
      "node": {
        "name": "@kangopenbanking/sdk",
        "version": "1.1.2",
        "status": "available",
        "package_manager": "https://www.npmjs.com/package/@kangopenbanking/sdk",
        "docs": "https://kangopenbanking.com/developer/guides/sdks#node"
      },
      "python": {
        "name": "kangopenbanking",
        "version": "0.0.1",
        "status": "experimental",
        "package_manager": "https://pypi.org/project/kangopenbanking/",
        "docs": "https://kangopenbanking.com/developer/guides/sdks#python"
      },
      "php": {
        "name": "kangopenbanking/sdk",
        "version": "1.1.2",
        "status": "available",
        "package_manager": "https://packagist.org/packages/kangopenbanking/sdk",
        "docs": "https://kangopenbanking.com/developer/guides/sdks#php"
      },
      "java": {
        "name": "com.kangopenbanking:kangopenbanking-sdk-typed",
        "status": "planned",
        "generator": "openapi-generator-cli (java, okhttp-gson)",
        "docs": "https://kangopenbanking.com/developer/guides/sdks#java"
      },
      "go": {
        "name": "github.com/kangopenbanking/sdk-go",
        "status": "planned",
        "docs": "https://kangopenbanking.com/developer/guides/sdks#go"
      },
      "ruby": {
        "name": "kangopenbanking",
        "status": "community-guide",
        "generator": "openapi-generator-cli (ruby)",
        "docs": "https://kangopenbanking.com/developer/guides/sdks#ruby"
      }
    },
    "x-postman-collection": "https://www.postman.com/kangfinance/kang-open-banking-api",
    "x-sdk-versions": {
      "node": "1.1.2",
      "python": "0.0.1",
      "php": "1.1.2",
      "go": "1.6.1"
    },
    "x-phase-10-audit": "https://kangopenbanking.com/developer/changelog#phase-10-cemac-coverage",
    "x-rate-limits": {
      "anonymous_per_minute": 60,
      "sandbox_per_minute": 300,
      "production_standard_per_minute": 1200
    }
  },
  "servers": [
    {
      "url": "https://api.kangopenbanking.com",
      "description": "Production"
    },
    {
      "url": "https://sandbox-api.kangopenbanking.com",
      "description": "Sandbox"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "tags": [
    {
      "name": "Monitoring",
      "description": "Health and readiness probes",
      "x-maturity": "ga",
      "x-maturity-note": "Generally available. Stable contract; suitable for production integration subject to licensing status noted in info.description."
    },
    {
      "name": "OAuth",
      "description": "OAuth 2.0 / OIDC / FAPI 1.0 Advanced (planned; not yet end-to-end)",
      "x-maturity": "ga",
      "x-maturity-note": "Generally available. Stable contract; suitable for production integration subject to licensing status noted in info.description."
    },
    {
      "name": "Authentication",
      "description": "Phone auth, PIN, password management",
      "x-maturity": "preview",
      "x-maturity-note": "Generally available. Stable contract; suitable for production integration subject to licensing status noted in info.description."
    },
    {
      "name": "Security",
      "description": "CAPTCHA, SCA (Strong Customer Authentication)",
      "x-maturity": "preview",
      "x-maturity-note": "Generally available. Stable contract; suitable for production integration subject to licensing status noted in info.description."
    },
    {
      "name": "Certificates",
      "description": "mTLS certificate management (RFC 8705)",
      "x-maturity": "preview",
      "x-maturity-note": "Sandbox/pilot. Implemented in sandbox for integration testing; not yet authorised for production traffic. May change before GA."
    },
    {
      "name": "AISP",
      "description": "Account Information Service Provider (PSD2/Open Banking)",
      "x-maturity": "ga",
      "x-maturity-note": "Generally available. Stable contract; suitable for production integration subject to licensing status noted in info.description."
    },
    {
      "name": "PISP",
      "description": "Payment Initiation Service Provider",
      "x-maturity": "ga",
      "x-maturity-note": "Generally available. Stable contract; suitable for production integration subject to licensing status noted in info.description."
    },
    {
      "name": "Consent Management",
      "description": "AISP/PISP consent lifecycle",
      "x-maturity": "ga",
      "x-maturity-note": "Generally available. Stable contract; suitable for production integration subject to licensing status noted in info.description."
    },
    {
      "name": "Credit Scoring",
      "description": "Credit scores, simulation, and reports",
      "x-maturity": "preview",
      "x-maturity-note": "Sandbox/pilot. Implemented in sandbox for integration testing; not yet authorised for production traffic. May change before GA."
    },
    {
      "name": "Loans",
      "description": "Loan products, applications, disbursement, repayment, schedules",
      "x-maturity": "preview",
      "x-maturity-note": "Sandbox/pilot. Implemented in sandbox for integration testing; not yet authorised for production traffic. May change before GA."
    },
    {
      "name": "Savings",
      "description": "Savings products, accounts, interest accrual",
      "x-maturity": "preview",
      "x-maturity-note": "Sandbox/pilot. Implemented in sandbox for integration testing; not yet authorised for production traffic. May change before GA."
    },
    {
      "name": "Ledger",
      "description": "Double-entry accounting (chart of accounts, journal entries)",
      "x-maturity": "preview",
      "x-maturity-note": "Sandbox/pilot. Implemented in sandbox for integration testing; not yet authorised for production traffic. May change before GA."
    },
    {
      "name": "Mobile Money",
      "description": "MTN & Orange Mobile Money integration",
      "x-maturity": "preview",
      "x-maturity-note": "Generally available. Stable contract; suitable for production integration subject to licensing status noted in info.description."
    },
    {
      "name": "Payments",
      "description": "Flutterwave & Stripe payment processing",
      "x-maturity": "preview",
      "x-maturity-note": "Generally available. Stable contract; suitable for production integration subject to licensing status noted in info.description."
    },
    {
      "name": "Banking Operations",
      "description": "Bulk transfers, exchange rates",
      "x-maturity": "preview",
      "x-maturity-note": "Generally available. Stable contract; suitable for production integration subject to licensing status noted in info.description."
    },
    {
      "name": "Virtual Cards",
      "description": "Virtual card issuance and management",
      "x-maturity": "preview",
      "x-maturity-note": "Sandbox/pilot. Implemented in sandbox for integration testing; not yet authorised for production traffic. May change before GA."
    },
    {
      "name": "Standards",
      "description": "ISO 20022 & SWIFT message processing",
      "x-maturity": "preview",
      "x-maturity-note": "Sandbox/pilot. Implemented in sandbox for integration testing; not yet authorised for production traffic. May change before GA."
    },
    {
      "name": "KYC & Compliance",
      "description": "Identity verification, sanctions screening",
      "x-maturity": "preview",
      "x-maturity-note": "Generally available. Stable contract; suitable for production integration subject to licensing status noted in info.description."
    },
    {
      "name": "Webhooks",
      "description": "Webhook registration and delivery",
      "x-maturity": "preview",
      "x-maturity-note": "Generally available. Stable contract; suitable for production integration subject to licensing status noted in info.description."
    },
    {
      "name": "Admin",
      "description": "Administrative endpoints (RBAC protected)",
      "x-maturity": "preview",
      "x-maturity-note": "Generally available. Stable contract; suitable for production integration subject to licensing status noted in info.description."
    },
    {
      "name": "Communications",
      "description": "Email, SMS, push notifications",
      "x-maturity": "preview",
      "x-maturity-note": "Generally available. Stable contract; suitable for production integration subject to licensing status noted in info.description."
    },
    {
      "name": "Settlement",
      "description": "Settlement calculation, processing, invoicing",
      "x-maturity": "preview",
      "x-maturity-note": "Sandbox/pilot. Implemented in sandbox for integration testing; not yet authorised for production traffic. May change before GA."
    },
    {
      "name": "Institution",
      "description": "Institution registration and management",
      "x-maturity": "preview",
      "x-maturity-note": "Sandbox/pilot. Implemented in sandbox for integration testing; not yet authorised for production traffic. May change before GA."
    },
    {
      "name": "CrediQ",
      "description": "Credit health monitoring and action plans",
      "x-maturity": "preview",
      "x-maturity-note": "Sandbox/pilot. Implemented in sandbox for integration testing; not yet authorised for production traffic. May change before GA."
    },
    {
      "name": "PostiQ",
      "description": "Address verification and postal codes",
      "x-maturity": "preview",
      "x-maturity-note": "Sandbox/pilot. Implemented in sandbox for integration testing; not yet authorised for production traffic. May change before GA."
    },
    {
      "name": "WooCommerce",
      "description": "WooCommerce payment plugin integration",
      "x-maturity": "preview",
      "x-maturity-note": "Sandbox/pilot. Implemented in sandbox for integration testing; not yet authorised for production traffic. May change before GA."
    },
    {
      "name": "Sandbox",
      "description": "Sandbox environment management",
      "x-maturity": "preview",
      "x-maturity-note": "Generally available. Stable contract; suitable for production integration subject to licensing status noted in info.description."
    },
    {
      "name": "Developer",
      "description": "Developer app registration",
      "x-maturity": "preview",
      "x-maturity-note": "Generally available. Stable contract; suitable for production integration subject to licensing status noted in info.description."
    },
    {
      "name": "Payment Gateway",
      "description": "Unified payment gateway — charges, payouts, refunds, disputes, settlements, beneficiaries, preauthorization, virtual accounts, merchant wallets, OTP validation, bank/BVN verification, payment links, subscriptions, split payments, tokenization, reconciliation",
      "x-maturity": "preview",
      "x-maturity-note": "Generally available. Stable contract; suitable for production integration subject to licensing status noted in info.description."
    },
    {
      "name": "Payment Facilitation",
      "description": "White-label payment processing — facilitated charges, settlement calculation and processing",
      "x-maturity": "preview",
      "x-maturity-note": "Sandbox/pilot. Implemented in sandbox for integration testing; not yet authorised for production traffic. May change before GA."
    },
    {
      "name": "Merchant Onboarding",
      "description": "Merchant lifecycle — registration, KYB verification, API keys, settlement accounts, webhooks",
      "x-maturity": "preview",
      "x-maturity-note": "Generally available. Stable contract; suitable for production integration subject to licensing status noted in info.description."
    },
    {
      "name": "Consumer Tools",
      "description": "Consumer financial tools — Piggy Bank (savings goals) and Njangi (group rotation savings)",
      "x-maturity": "preview",
      "x-maturity-note": "Sandbox/pilot. Implemented in sandbox for integration testing; not yet authorised for production traffic. May change before GA."
    },
    {
      "name": "Bank Directory",
      "description": "Bank/ASPSP registration, lifecycle management, PSU linking, and public directory",
      "x-maturity": "preview",
      "x-maturity-note": "Generally available. Stable contract; suitable for production integration subject to licensing status noted in info.description."
    },
    {
      "name": "Bank Connectors",
      "description": "Bank connector registration, mTLS certificates, data ingestion (accounts, transactions), health monitoring, and payment status callbacks",
      "x-maturity": "preview",
      "x-maturity-note": "Sandbox/pilot. Implemented in sandbox for integration testing; not yet authorised for production traffic. May change before GA."
    },
    {
      "name": "Interbank",
      "description": "Interbank payment engine — ISO 20022 pacs.008/pacs.002 messaging, participant management, and payment lifecycle (10-state machine)",
      "x-maturity": "preview",
      "x-maturity-note": "Sandbox/pilot. Implemented in sandbox for integration testing; not yet authorised for production traffic. May change before GA."
    },
    {
      "name": "Pay by Bank",
      "description": "Redirect-based Pay by Bank with Strong Customer Authentication (SCA) — payment intents, hosted authorization, webhook events (authorized, submitted, completed, failed)",
      "x-maturity": "preview",
      "x-maturity-note": "Sandbox/pilot. Implemented in sandbox for integration testing; not yet authorised for production traffic. May change before GA."
    },
    {
      "name": "Provider Webhooks (Inbound)",
      "description": "Inbound webhook receivers for payment providers (Stripe, Flutterwave, PayPal). Secured by provider-specific signature verification — no bearer auth required. Paths follow /v1/webhooks/providers/{provider} convention.",
      "x-maturity": "preview",
      "x-maturity-note": "Generally available. Stable contract; suitable for production integration subject to licensing status noted in info.description."
    },
    {
      "name": "Overdraft",
      "description": "Account overdraft facility — eligibility, limits, approval, suspension, and reinstatement lifecycle",
      "x-maturity": "preview",
      "x-maturity-note": "Sandbox/pilot. Implemented in sandbox for integration testing; not yet authorised for production traffic. May change before GA."
    },
    {
      "name": "Approval Workflows",
      "description": "Multi-level approval workflows for high-value transactions and withdrawal requests",
      "x-maturity": "preview",
      "x-maturity-note": "Sandbox/pilot. Implemented in sandbox for integration testing; not yet authorised for production traffic. May change before GA."
    },
    {
      "name": "Directory",
      "description": "Public institution and bank directory — read-only public endpoints",
      "x-maturity": "ga",
      "x-maturity-note": "Generally available. Stable contract; suitable for production integration subject to licensing status noted in info.description."
    },
    {
      "name": "Operational Controls",
      "description": "Internal operational controls — teller transactions, withdrawal policies, and staff authorisations",
      "x-maturity": "preview",
      "x-maturity-note": "Sandbox/pilot. Implemented in sandbox for integration testing; not yet authorised for production traffic. May change before GA."
    },
    {
      "name": "Standards - ISO 20022",
      "description": "ISO 20022 message generation and parsing — pacs.004, pacs.008, pacs.009, pacs.002, camt.052, camt.053, camt.054, camt.056, and pain.001 message types for interbank settlement, payment return, FI credit transfer, account reporting, debit/credit notification, payment cancellation, and corporate treasury workflows.",
      "x-maturity": "preview",
      "x-maturity-note": "Sandbox/pilot. Implemented in sandbox for integration testing; not yet authorised for production traffic. May change before GA."
    },
    {
      "name": "Merchants",
      "description": "Merchants endpoints",
      "x-maturity": "preview",
      "x-maturity-note": "Generally available. Stable contract; suitable for production integration subject to licensing status noted in info.description."
    },
    {
      "name": "Gateway",
      "description": "Gateway endpoints",
      "x-maturity": "preview",
      "x-maturity-note": "Sandbox/pilot. Implemented in sandbox for integration testing; not yet authorised for production traffic. May change before GA."
    },
    {
      "name": "BankConnectors",
      "description": "Bank connector kit endpoints — SFTP file imports, batch payment uploads, mapping rules, reconciliation tracking. See /developer/connectors/bank-connector-runbook.",
      "externalDocs": {
        "description": "Connector runbook",
        "url": "https://kangopenbanking.com/developer/connectors/bank-connector-runbook"
      },
      "x-maturity": "preview",
      "x-maturity-note": "Sandbox/pilot. Implemented in sandbox for integration testing; not yet authorised for production traffic. May change before GA."
    },
    {
      "name": "Specification",
      "description": "OpenAPI specification metadata and version diff",
      "x-maturity": "ga",
      "x-maturity-note": "Generally available. Stable contract; suitable for production integration subject to licensing status noted in info.description."
    },
    {
      "name": "Issuing",
      "description": "Virtual Card Issuing for Banks and Developers (Kora middleware).",
      "x-maturity": "preview",
      "x-maturity-note": "Sandbox/pilot. Implemented in sandbox for integration testing; not yet authorised for production traffic. May change before GA."
    },
    {
      "name": "Budgeting",
      "description": "Smart budgeting, spending analytics, XAF-native savings goals, Njangi integration, and trilingual (EN/FR/Pidgin) AI-powered financial advice. Reads from existing charge, transaction, account, and savings data streams — no new data collection.",
      "externalDocs": {
        "description": "Budgeting integration guide",
        "url": "https://kangopenbanking.com/developer/guides/budgeting"
      },
      "x-maturity": "preview",
      "x-maturity-note": "Sandbox/pilot. Implemented in sandbox for integration testing; not yet authorised for production traffic. May change before GA."
    },
    {
      "name": "Consents",
      "description": "Unified AISP/PISP/CBPII consent lifecycle.",
      "x-maturity": "ga",
      "x-maturity-note": "Generally available. Stable contract; suitable for production integration subject to licensing status noted in info.description."
    },
    {
      "name": "Statements",
      "description": "ISO 20022 camt.053 + PDF + CSV statement generation.",
      "x-maturity": "preview",
      "x-maturity-note": "Generally available. Stable contract; suitable for production integration subject to licensing status noted in info.description."
    },
    {
      "name": "Platform",
      "description": "Platform-wide metadata (rate limits, health, capabilities).",
      "x-maturity": "preview",
      "x-maturity-note": "Generally available. Stable contract; suitable for production integration subject to licensing status noted in info.description."
    },
    {
      "name": "Agents",
      "description": "Agent (cash-in/out) banking. CEMAC-wide registry, float management, customer cash transactions. See BIS Agent Banking Guidelines (2018) and Mojaloop v1.1.",
      "x-maturity": "experimental",
      "x-maturity-note": "Experimental. Reference shape only; implementation is partial and may change without a major version bump until promoted."
    },
    {
      "name": "USSD",
      "description": "Session-based USSD menu engine for feature-phone banking. ETSI TS 102 226.",
      "x-maturity": "experimental",
      "x-maturity-note": "Experimental. Reference shape only; implementation is partial and may change without a major version bump until promoted."
    },
    {
      "name": "QR & Offline",
      "description": "EMVCo-compliant QR + signed offline-payment tokens. EMVCo QR Spec v1.1.",
      "x-maturity": "experimental",
      "x-maturity-note": "Experimental. Reference shape only; implementation is partial and may change without a major version bump until promoted."
    },
    {
      "name": "CEMAC Remittance",
      "description": "Cross-border XAF/XAF remittance inside the six BEAC-zone countries. BEAC Règlement N°02/CEMAC.",
      "x-maturity": "experimental",
      "x-maturity-note": "Experimental. Reference shape only; implementation is partial and may change without a major version bump until promoted."
    },
    {
      "name": "Reference",
      "description": "Reference data endpoints: institution directories, corridors, currencies and other static lookups required to construct valid requests."
    },
    {
      "name": "Identity & KYC",
      "description": "Identity verification, KYC and KYB endpoints covering document submission, verification status and compliance decisions."
    }
  ],
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "JWT",
        "description": "OAuth 2.0 access token",
        "x-scopes": {
          "description": "Reconciled scope registry enforced by the gateway. Keys MUST carry at least one scope from this list. Scope values are explicit per RFC 6749 Section 3.3; wildcard scopes are not issued and are rejected at authorisation time (FAPI 1.0 Advanced Section 5.2.2). The former `admin:*` wildcard is superseded by `admin:read` and `admin:write`.",
          "scopes": {
            "charges:read": "Read charges, refunds, captures",
            "charges:write": "Create, capture, refund, reverse, or void charges",
            "payouts:read": "Read payouts, settlements, beneficiaries",
            "payouts:write": "Create or cancel payouts and beneficiaries",
            "customers:read": "Read customers, tokens, payment methods",
            "customers:write": "Create, update, or delete customers and tokens",
            "webhooks:manage": "Create, update, rotate, or delete webhook endpoints",
            "webhooks:replay": "Replay deliveries from the dead-letter queue",
            "reports:read": "Read settlements, exports, audit logs, reconciliation reports",
            "compliance:read": "Read KYC/KYB, AML screening, dispute evidence",
            "compliance:write": "Submit KYC/KYB documents, dispute evidence, SAR filings",
            "banking:read": "Read banking resources: accounts, balances, transactions, statements",
            "banking:write": "Initiate banking operations: transfers, payments, standing instructions",
            "merchants:read": "Read merchant profiles, directories, terminals, and settlement views",
            "merchants:write": "Create or update merchant profiles, terminals, and directory entries",
            "gateway:read": "Read gateway resources: charges, refunds, payouts, subscriptions, reports",
            "admin:read": "Read administrative resources (administrative credentials only)",
            "admin:write": "Perform administrative mutations (administrative credentials only)"
          }
        }
      },
      "mtls": {
        "type": "mutualTLS",
        "description": "Client certificate (RFC 8705)",
        "x-rfc": "RFC 8705 Section 2.1"
      },
      "oauth2": {
        "type": "oauth2",
        "flows": {
          "authorizationCode": {
            "authorizationUrl": "https://api.kangopenbanking.com/v1/oauth/authorize",
            "tokenUrl": "https://api.kangopenbanking.com/v1/oauth/token",
            "scopes": {
              "openid": "OpenID Connect",
              "accounts": "Read account information",
              "balances": "Read balances",
              "transactions": "Read transactions",
              "payments": "Initiate payments",
              "offline_access": "Refresh tokens",
              "payments:write": "Initiate payments on behalf of the PSU",
              "accounts:read": "Read account information on behalf of the PSU",
              "profile": "Read basic PSU profile information",
              "banking:read": "Read banking resources: accounts, balances, transactions, statements",
              "banking:write": "Initiate banking operations: transfers, payments, standing instructions",
              "merchants:read": "Read merchant profiles, directories, terminals, and settlement views",
              "merchants:write": "Create or update merchant profiles, terminals, and directory entries",
              "gateway:read": "Read gateway resources: charges, refunds, payouts, subscriptions, reports",
              "admin:read": "Read administrative resources (administrative credentials only)",
              "admin:write": "Perform administrative mutations (administrative credentials only)"
            },
            "refreshUrl": "https://api.kangopenbanking.com/v1/oauth/token"
          }
        }
      },
      "WebhookSignature": {
        "type": "apiKey",
        "in": "header",
        "name": "X-Webhook-Signature",
        "description": "HMAC-SHA256 signature over `${timestamp}.${body}` using the endpoint secret. Format `t=<ts>,v1=<hex>`. Reject if `|now - t| > 300s` (Stripe/OWASP convention)."
      },
      "MerchantSecretKey": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "MerchantSecretKey",
        "description": "Server-side merchant secret key issued in Merchant Portal → API Keys. Sandbox keys are prefixed `sk_test_`, production keys `sk_live_`. Never expose in browsers or mobile clients. Sent as `Authorization: Bearer <key>`; `X-API-Key: <key>` is accepted as an alias. The key prefix determines the environment — a `sk_test_` key is rejected against live merchants and vice versa.",
        "x-key-prefix": "sk_",
        "x-environments": {
          "sandbox": "sk_test_",
          "production": "sk_live_"
        },
        "x-added-in": "4.54.0",
        "x-corrected-in": "4.54.2",
        "x-correction-note": "4.54.0 incorrectly documented the prefix as `kob_sec_`; that prefix belongs to institution (bank/FI) tenant keys — see InstitutionSecretKey."
      },
      "PublishableKey": {
        "type": "apiKey",
        "in": "header",
        "name": "X-Publishable-Key",
        "description": "Client-safe publishable key prefixed with `kob_pub_`. Read-only surface (tokenisation, checkout session creation). Safe to embed in browser or mobile clients. Deprecated: no operation accepts this credential today. Scheduled for removal in the 5.0.0 break; not removed now because Standing Order 1 forbids removing a security scheme name without a major version increment.",
        "x-key-prefix": "kob_pub_",
        "x-added-in": "4.54.0",
        "x-sunset": "4.55.0",
        "x-deprecated": true
      },
      "privateKeyJwt": {
        "type": "apiKey",
        "in": "query",
        "name": "client_assertion",
        "description": "RFC 7523 §2.2 `private_key_jwt` client authentication. The client sends `client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer` and `client_assertion=<signed JWT>` as `application/x-www-form-urlencoded` body parameters. OpenAPI 3.1 has no request-body security scheme location, so `in: query` is declared as the closest expressible location. The query string MUST NOT be used to transmit the assertion.",
        "x-transport": "request-body",
        "x-rfc": "RFC 7523 Section 2.2"
      },
      "StripeSignature": {
        "type": "apiKey",
        "in": "header",
        "name": "stripe-signature",
        "description": "Stripe webhook signature. Format `t=<unix-ts>,v1=<hex HMAC-SHA256>` over `${t}.${rawBody}` using the endpoint signing secret. Deliveries older than 300s are rejected.",
        "x-signature": {
          "algorithm": "HMAC-SHA256",
          "payload": "{timestamp}.{rawBody}",
          "toleranceSeconds": 300
        }
      },
      "FlutterwaveSignature": {
        "type": "apiKey",
        "in": "header",
        "name": "verif-hash",
        "description": "Flutterwave webhook verification hash. Constant secret hash compared in constant time against the configured endpoint secret.",
        "x-signature": {
          "algorithm": "shared-secret",
          "payload": "none",
          "toleranceSeconds": null
        }
      },
      "PaypalTransmissionSignature": {
        "type": "apiKey",
        "in": "header",
        "name": "paypal-transmission-sig",
        "description": "PayPal webhook transmission signature. Base64 RSA signature verified with the certificate at `paypal-cert-url` using the algorithm in `paypal-auth-algo`, over `{transmission_id}|{transmission_time}|{webhook_id}|{crc32(rawBody)}`.",
        "x-signature": {
          "algorithm": "SHA256withRSA",
          "payload": "{transmission_id}|{transmission_time}|{webhook_id}|{crc32(rawBody)}",
          "toleranceSeconds": 300
        }
      },
      "WooCommerceSignature": {
        "type": "apiKey",
        "in": "header",
        "name": "x-wc-webhook-signature",
        "description": "WooCommerce webhook signature. Base64 HMAC-SHA256 over the raw request body using the integration webhook secret.",
        "x-signature": {
          "algorithm": "HMAC-SHA256",
          "payload": "{rawBody}",
          "toleranceSeconds": null
        }
      },
      "NiumSignature": {
        "type": "apiKey",
        "in": "header",
        "name": "x-nium-signature",
        "description": "Nium webhook signature. Hex HMAC-SHA256 over `${x-nium-timestamp}.${rawBody}` using the configured Nium webhook secret.",
        "x-signature": {
          "algorithm": "HMAC-SHA256",
          "payload": "{x-nium-timestamp}.{rawBody}",
          "toleranceSeconds": 300
        }
      },
      "InstitutionSecretKey": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "InstitutionSecretKey",
        "description": "Tenant-scoped institution (bank/FI) secret key. Test keys are prefixed `kob_sec_test_`, live keys `kob_sec_live_`. Resolves to an institution rather than a single user and carries an explicit scope allow-list. The key environment must match the target environment. Sent as `Authorization: Bearer <key>` or `X-API-Key: <key>`.",
        "x-key-prefix": "kob_sec_",
        "x-environments": {
          "test": "kob_sec_test_",
          "live": "kob_sec_live_"
        },
        "x-added-in": "4.54.2"
      },
      "LegacySandboxKey": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "LegacySandboxKey",
        "description": "Legacy developer sandbox key prefixed `sbx_`. Still accepted against sandbox resources for backward compatibility. New integrations must use `sk_test_` merchant keys or OAuth clients.",
        "x-key-prefix": "sbx_",
        "x-added-in": "4.54.2",
        "x-deprecated": true
      }
    },
    "schemas": {
      "SandboxWebhookSendResult": {
        "type": "object",
        "description": "Result of dispatching a test webhook to a registered sandbox endpoint. Returned by POST /v1/sandbox/webhooks/send-test.",
        "required": [
          "object",
          "livemode",
          "endpoint_id",
          "event_type",
          "delivery_id",
          "status",
          "dispatched_at"
        ],
        "properties": {
          "object": {
            "type": "string",
            "enum": [
              "sandbox.webhook_send_result"
            ],
            "description": "Discriminator for response envelope."
          },
          "livemode": {
            "type": "boolean",
            "enum": [
              false
            ],
            "description": "Always false for sandbox responses."
          },
          "endpoint_id": {
            "type": "string",
            "description": "Identifier of the webhook endpoint that received the test event."
          },
          "event_type": {
            "type": "string",
            "description": "The event type used for the test dispatch (e.g. charge.successful)."
          },
          "delivery_id": {
            "type": "string",
            "description": "Unique identifier for this delivery attempt; usable with the deliveries API for replay or inspection."
          },
          "status": {
            "type": "string",
            "enum": [
              "queued",
              "delivered",
              "failed"
            ],
            "description": "Initial delivery status. queued = accepted for asynchronous delivery; delivered = synchronous 2xx received; failed = synchronous failure."
          },
          "response_status": {
            "type": "integer",
            "minimum": 100,
            "maximum": 599,
            "description": "HTTP status code returned by the merchant endpoint when status is delivered or failed."
          },
          "dispatched_at": {
            "type": "string",
            "format": "date-time",
            "description": "RFC 3339 timestamp at which the test was dispatched."
          },
          "request_id": {
            "type": "string",
            "description": "Correlation identifier echoed in the X-Request-ID response header."
          }
        }
      },
      "SandboxResetResult": {
        "type": "object",
        "description": "Result of resetting sandbox data for the calling merchant. Returned by POST /v1/sandbox/reset. Production data is never affected.",
        "required": [
          "object",
          "livemode",
          "merchant_id",
          "reset_at",
          "cleared"
        ],
        "properties": {
          "object": {
            "type": "string",
            "enum": [
              "sandbox.reset_result"
            ],
            "description": "Discriminator for response envelope."
          },
          "livemode": {
            "type": "boolean",
            "enum": [
              false
            ],
            "description": "Always false for sandbox responses."
          },
          "merchant_id": {
            "type": "string",
            "description": "Identifier of the merchant whose sandbox data was reset."
          },
          "reset_at": {
            "type": "string",
            "format": "date-time",
            "description": "RFC 3339 timestamp at which the reset completed."
          },
          "cleared": {
            "type": "object",
            "description": "Counts of records removed by category. Categories with zero rows may be omitted.",
            "properties": {
              "charges": {
                "type": "integer",
                "minimum": 0
              },
              "payments": {
                "type": "integer",
                "minimum": 0
              },
              "refunds": {
                "type": "integer",
                "minimum": 0
              },
              "payouts": {
                "type": "integer",
                "minimum": 0
              },
              "webhook_deliveries": {
                "type": "integer",
                "minimum": 0
              },
              "customers": {
                "type": "integer",
                "minimum": 0
              }
            }
          },
          "request_id": {
            "type": "string",
            "description": "Correlation identifier echoed in the X-Request-ID response header."
          }
        }
      },
      "WebhookReplayRequest": {
        "type": "object",
        "description": "Optional body for a webhook delivery replay. Both fields are inferred from the URL when omitted; supplying them keeps the request compatible with action-based router invocations.",
        "properties": {
          "endpoint_id": {
            "type": "string",
            "format": "uuid",
            "description": "Endpoint identifier. Optional; defaults to the {endpointId} path parameter."
          },
          "delivery_id": {
            "type": "string",
            "format": "uuid",
            "description": "Original delivery identifier. Optional; defaults to the {deliveryId} path parameter."
          }
        },
        "required": [
          "delivery_id"
        ]
      },
      "WebhookReplayResult": {
        "type": "object",
        "description": "Outcome of a single-delivery webhook replay. A new delivery row is created so the original record remains intact for audit. Manual replays are one-shot and do not enter the automatic retry chain.",
        "required": [
          "replay_delivery_id",
          "original_delivery_id",
          "endpoint_id",
          "status",
          "created_at"
        ],
        "properties": {
          "replay_delivery_id": {
            "type": "string",
            "format": "uuid",
            "description": "Identifier of the newly created delivery record for this replay attempt."
          },
          "original_delivery_id": {
            "type": "string",
            "format": "uuid",
            "description": "Identifier of the delivery that was replayed."
          },
          "endpoint_id": {
            "type": "string",
            "format": "uuid"
          },
          "status": {
            "type": "string",
            "enum": [
              "delivered",
              "failed"
            ],
            "description": "Outcome of the replay attempt."
          },
          "response_status": {
            "type": [
              "integer",
              "null"
            ],
            "description": "HTTP status code returned by the receiver, or null if the request never completed."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "WebhookEndpointHealth": {
        "type": "object",
        "description": "24-hour operational health snapshot for a webhook endpoint. Used by integrators to monitor receiver reliability and by support to triage incidents.",
        "required": [
          "endpoint_id",
          "url",
          "is_active",
          "window",
          "health",
          "totals",
          "generated_at"
        ],
        "properties": {
          "endpoint_id": {
            "type": "string",
            "format": "uuid"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "is_active": {
            "type": "boolean"
          },
          "window": {
            "type": "string",
            "enum": [
              "24h"
            ],
            "description": "Observation window for this snapshot."
          },
          "health": {
            "type": "string",
            "enum": [
              "healthy",
              "degraded",
              "unhealthy",
              "idle"
            ],
            "description": "Overall classification: idle (no traffic), healthy (>=95% success), degraded (>=75%), unhealthy (<75%)."
          },
          "totals": {
            "type": "object",
            "required": [
              "total",
              "delivered",
              "failed",
              "pending",
              "exhausted"
            ],
            "properties": {
              "total": {
                "type": "integer",
                "minimum": 0
              },
              "delivered": {
                "type": "integer",
                "minimum": 0
              },
              "failed": {
                "type": "integer",
                "minimum": 0
              },
              "pending": {
                "type": "integer",
                "minimum": 0
              },
              "exhausted": {
                "type": "integer",
                "minimum": 0
              }
            }
          },
          "success_rate_pct": {
            "type": [
              "number",
              "null"
            ],
            "format": "float",
            "minimum": 0,
            "maximum": 100,
            "description": "Percentage of deliveries with status=delivered. Null when there has been no traffic."
          },
          "latency_ms": {
            "type": "object",
            "description": "End-to-end latency from delivery creation to successful acknowledgement, in milliseconds. Null fields indicate insufficient samples.",
            "properties": {
              "p50": {
                "type": [
                  "integer",
                  "null"
                ],
                "minimum": 0
              },
              "p95": {
                "type": [
                  "integer",
                  "null"
                ],
                "minimum": 0
              },
              "p99": {
                "type": [
                  "integer",
                  "null"
                ],
                "minimum": 0
              }
            }
          },
          "last_delivery_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "last_failure_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "generated_at": {
            "type": "string",
            "format": "date-time",
            "description": "Timestamp at which this snapshot was computed."
          }
        }
      },
      "DcrRegistrationRequest": {
        "type": "object",
        "description": "Dynamic Client Registration request per RFC 7591, with FAPI 1.0 Advanced extensions. The software_statement is a signed JWT (SSA) issued by the KOB Directory containing the TPP's identity claims.",
        "properties": {
          "software_statement": {
            "type": "string",
            "format": "jwt",
            "description": "Signed Software Statement Assertion (SSA) JWT from the KOB Directory. Must contain software_id, software_client_name, and software_roles claims (RFC 7591 Section 2.3).",
            "example": "eyJhbGciOiJQUzI1NiIsInR5cCI6IkpXVCJ9.eyJzb2Z0d2FyZV9pZCI6InRwcF8wMDEiLCJzb2Z0d2FyZV9jbGllbnRfbmFtZSI6IkZpblRlY2ggQXBwIENhbWVyb3VuIiwic29mdHdhcmVfcm9sZXMiOlsiQUlTUCIsIlBJU1AiXSwic29mdHdhcmVfcmVkaXJlY3RfdXJpcyI6WyJodHRwczovL2FwcC5leGFtcGxlLmNvbS9jYWxsYmFjayJdfQ.signature"
          },
          "redirect_uris": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uri"
            },
            "description": "OAuth 2.0 redirect URIs. Must use HTTPS in production (RFC 7591 Section 2).",
            "example": [
              "https://app.example.com/callback",
              "https://app.example.com/silent-renew"
            ]
          },
          "client_name": {
            "type": "string",
            "description": "Human-readable name of the client application. If omitted, extracted from software_statement (RFC 7591 Section 2).",
            "example": "FinTech App Cameroun"
          },
          "token_endpoint_auth_method": {
            "type": "string",
            "description": "Authentication method for the token endpoint. The default is `client_secret_basic` with PKCE, which is implemented end-to-end today. `tls_client_auth` and `private_key_jwt` are accepted for forward compatibility but are planned (FAPI 1.0 Advanced §5.2.2) and not yet enforced end-to-end. The `none` value is explicitly NOT permitted. Public/native clients MUST use PKCE.",
            "enum": [
              "client_secret_basic",
              "client_secret_post",
              "tls_client_auth",
              "private_key_jwt"
            ],
            "default": "client_secret_basic"
          },
          "grant_types": {
            "type": "array",
            "description": "OAuth 2.0 grant types the client will use (RFC 7591 Section 2).",
            "items": {
              "type": "string",
              "enum": [
                "authorization_code",
                "refresh_token",
                "client_credentials"
              ]
            },
            "default": [
              "authorization_code",
              "refresh_token"
            ],
            "example": [
              "authorization_code",
              "refresh_token"
            ]
          },
          "response_types": {
            "type": "array",
            "description": "OAuth 2.0 response types the client will use (RFC 7591 Section 2).",
            "items": {
              "type": "string",
              "enum": [
                "code",
                "code id_token"
              ]
            },
            "default": [
              "code"
            ]
          },
          "scope": {
            "type": "string",
            "description": "Space-delimited list of requested scopes (RFC 7591 Section 2).",
            "default": "accounts payments",
            "example": "accounts payments openid"
          },
          "jwks_uri": {
            "type": "string",
            "format": "uri",
            "description": "URL of the client's JSON Web Key Set document. Mutually exclusive with jwks (RFC 7591 Section 2).",
            "example": "https://app.example.com/.well-known/jwks.json"
          },
          "jwks": {
            "type": "object",
            "description": "Inline JSON Web Key Set. Mutually exclusive with jwks_uri. Use when the client cannot host a JWKS endpoint (RFC 7591 Section 2).",
            "properties": {
              "keys": {
                "type": "array",
                "items": {
                  "type": "object"
                }
              }
            }
          },
          "application_type": {
            "type": "string",
            "enum": [
              "web",
              "native"
            ],
            "default": "web",
            "description": "Kind of application (OIDC Core Section 2)."
          },
          "id_token_signed_response_alg": {
            "type": "string",
            "enum": [
              "PS256",
              "ES256",
              "RS256"
            ],
            "default": "PS256",
            "description": "Algorithm for signing ID Tokens issued to this client. PS256 required for FAPI 1.0 Advanced (FAPI 1.0 ADV Section 5.2.2)."
          },
          "request_object_signing_alg": {
            "type": "string",
            "enum": [
              "PS256",
              "ES256"
            ],
            "default": "PS256",
            "description": "Algorithm used to sign Request Objects sent to this server (FAPI 1.0 ADV Section 5.2.2)."
          }
        },
        "required": [
          "client_name",
          "redirect_uris",
          "token_endpoint_auth_method"
        ]
      },
      "DcrRegistrationResponse": {
        "type": "object",
        "required": [
          "client_id",
          "client_secret",
          "client_name",
          "software_id",
          "redirect_uris",
          "grant_types",
          "response_types",
          "token_endpoint_auth_method",
          "scope",
          "environment",
          "client_id_issued_at"
        ],
        "description": "Dynamic Client Registration response per RFC 7591. The client_secret is returned in plaintext exactly once at registration time and must be stored securely by the caller.",
        "properties": {
          "client_id": {
            "type": "string",
            "description": "Unique client identifier issued by the authorization server.",
            "example": "tpp_a1b2c3d4-e5f6-7890-abcd-ef1234567890"
          },
          "client_secret": {
            "type": "string",
            "description": "Client secret. Returned in plaintext ONLY at registration time. Store securely; it cannot be retrieved again.",
            "example": "kob_sec_7f3a9b2c4d5e6f1a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f"
          },
          "client_name": {
            "type": "string",
            "description": "Human-readable name of the registered client.",
            "example": "FinTech App Cameroun"
          },
          "software_id": {
            "type": "string",
            "description": "Software identifier extracted from the SSA.",
            "example": "tpp_001"
          },
          "software_roles": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "AISP",
                "PISP",
                "CBPII"
              ]
            },
            "description": "Roles granted to the software (from SSA claims).",
            "example": [
              "AISP",
              "PISP"
            ]
          },
          "redirect_uris": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uri"
            },
            "description": "Registered redirect URIs.",
            "example": [
              "https://app.example.com/callback"
            ]
          },
          "grant_types": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Granted OAuth 2.0 grant types.",
            "example": [
              "authorization_code",
              "refresh_token"
            ]
          },
          "response_types": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Granted OAuth 2.0 response types.",
            "example": [
              "code"
            ]
          },
          "token_endpoint_auth_method": {
            "type": "string",
            "description": "Registered authentication method for the token endpoint.",
            "example": "client_secret_basic"
          },
          "jwks_uri": {
            "type": "string",
            "format": "uri",
            "description": "Registered JWKS endpoint (if provided).",
            "example": "https://app.example.com/.well-known/jwks.json"
          },
          "scope": {
            "type": "string",
            "description": "Granted scopes (space-delimited).",
            "example": "accounts payments"
          },
          "environment": {
            "type": "string",
            "enum": [
              "sandbox",
              "production"
            ],
            "description": "Environment the client is registered in. New registrations default to sandbox.",
            "example": "sandbox"
          },
          "client_id_issued_at": {
            "type": "integer",
            "description": "Unix timestamp (seconds) when the client_id was issued.",
            "example": 1710504000
          }
        }
      },
      "Error": {
        "type": "object",
        "required": [
          "error",
          "error_code",
          "message",
          "error_id",
          "timestamp"
        ],
        "properties": {
          "error": {
            "type": "string",
            "description": "Machine-readable error code",
            "example": "invalid_request"
          },
          "error_code": {
            "type": "string",
            "description": "Domain-prefixed error code",
            "example": "AUTH_001"
          },
          "message": {
            "type": "string",
            "description": "Human-readable description",
            "example": "The request is missing a required parameter."
          },
          "details": {
            "type": "object",
            "description": "Additional context",
            "additionalProperties": true
          },
          "error_id": {
            "type": "string",
            "description": "Unique error trace ID",
            "example": "err_a1b2c3d4"
          },
          "timestamp": {
            "type": "string",
            "format": "date-time"
          }
        },
        "deprecated": true,
        "x-successor": "#/components/schemas/ProblemDetails",
        "x-sunset": "4.55.0",
        "description": "DEPRECATED — bespoke error envelope retained for backward compatibility. Every error response also serves RFC 7807 Problem Details via application/problem+json. This schema is scheduled for removal on the 4.55.0 train; migrate to ProblemDetails."
      },
      "Pagination": {
        "type": "object",
        "description": "Standard pagination metadata for list responses",
        "required": [
          "page",
          "limit",
          "total",
          "has_next"
        ],
        "properties": {
          "page": {
            "type": "integer",
            "description": "Current page number (1-based)",
            "example": 1
          },
          "limit": {
            "type": "integer",
            "description": "Number of items per page",
            "example": 20
          },
          "total": {
            "type": "integer",
            "description": "Total number of items across all pages",
            "example": 150
          },
          "has_next": {
            "type": "boolean",
            "description": "Whether a next page exists",
            "example": true
          },
          "next_cursor": {
            "type": "string",
            "description": "Opaque cursor for the next page (cursor-based pagination)",
            "example": "eyJpZCI6IjEyMyJ9"
          }
        }
      },
      "Account": {
        "type": "object",
        "properties": {
          "account_id": {
            "type": "string",
            "format": "uuid"
          },
          "account_number": {
            "type": "string",
            "example": "CM21 10003 00100 0123456789 023"
          },
          "account_type": {
            "type": "string",
            "enum": [
              "checking",
              "savings",
              "loan",
              "business"
            ]
          },
          "account_subtype": {
            "type": "string",
            "enum": [
              "personal_current",
              "business_current",
              "fixed_deposit",
              "savings_regular"
            ]
          },
          "identification_scheme": {
            "type": "string",
            "enum": [
              "LOCAL_BANK",
              "MOMO",
              "IBAN",
              "DOMESTIC_RIB"
            ],
            "description": "Account identifier scheme"
          },
          "identification_value": {
            "type": "string",
            "description": "Raw account identifier value"
          },
          "currency": {
            "type": "string",
            "default": "XAF",
            "example": "XAF",
            "enum": [
              "XAF",
              "XOF",
              "USD",
              "EUR",
              "GBP",
              "CNY",
              "NGN",
              "GHS",
              "KES",
              "ZAR"
            ],
            "description": "ISO 4217 currency code. Default is XAF (Central African CFA Franc)."
          },
          "balance": {
            "type": "string",
            "example": "1500000",
            "pattern": "^[0-9]{1,15}$",
            "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits). Must be consistent with the currency field."
          },
          "account_holder_name": {
            "type": "string",
            "example": "Jean-Pierre Kamga"
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "inactive",
              "frozen",
              "closed"
            ]
          },
          "opened_date": {
            "type": "string",
            "format": "date",
            "example": "2025-03-15"
          },
          "rib_bank_code": {
            "type": "string",
            "maxLength": 5,
            "example": "10005",
            "description": "First 5 digits of RIB (bank code)"
          },
          "rib_branch_code": {
            "type": "string",
            "maxLength": 5,
            "example": "00100",
            "description": "Digits 6-10 of RIB (branch code)"
          },
          "rib_account_number": {
            "type": "string",
            "maxLength": 11,
            "example": "01234567890",
            "description": "Digits 11-21 of RIB (account number)"
          },
          "rib_key": {
            "type": "string",
            "maxLength": 2,
            "example": "23",
            "description": "Digits 22-23 of RIB (MOD-97 key)"
          },
          "swift_bic": {
            "type": "string",
            "maxLength": 11,
            "example": "AFRIACMCXXX",
            "description": "SWIFT/BIC code (8 or 11 chars)"
          },
          "account_country": {
            "type": "string",
            "maxLength": 2,
            "example": "CM",
            "description": "ISO 3166-1 alpha-2 country code"
          }
        },
        "required": [
          "account_id",
          "account_type",
          "account_subtype",
          "currency",
          "identification_scheme",
          "identification_value",
          "status"
        ],
        "description": "An Open Banking account resource: identification, type, currency and current balances for a single payment or savings account held at a connected institution."
      },
      "Balance": {
        "type": "object",
        "properties": {
          "balance_type": {
            "type": "string",
            "enum": [
              "ClosingAvailable",
              "ClosingBooked",
              "Expected",
              "ForwardAvailable"
            ]
          },
          "amount": {
            "type": "string",
            "example": "1500000",
            "pattern": "^[0-9]{1,15}$",
            "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits). Must be consistent with the currency field."
          },
          "currency": {
            "type": "string",
            "example": "XAF",
            "enum": [
              "XAF",
              "XOF",
              "USD",
              "EUR",
              "GBP",
              "CNY",
              "NGN",
              "GHS",
              "KES",
              "ZAR"
            ],
            "default": "XAF",
            "description": "ISO 4217 currency code. Default is XAF (Central African CFA Franc)."
          },
          "credit_debit_indicator": {
            "type": "string",
            "enum": [
              "Credit",
              "Debit"
            ]
          },
          "date_time": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "balance_type",
          "amount",
          "currency",
          "credit_debit_indicator",
          "date_time"
        ],
        "description": "A point-in-time balance for an account, qualified by balance type and credit/debit indicator as defined by the Open Banking balance model."
      },
      "Transaction": {
        "type": "object",
        "properties": {
          "transaction_id": {
            "type": "string",
            "format": "uuid"
          },
          "amount": {
            "type": "string",
            "example": "25000",
            "pattern": "^[0-9]{1,15}$",
            "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits). Must be consistent with the currency field."
          },
          "currency": {
            "type": "string",
            "example": "XAF",
            "enum": [
              "XAF",
              "XOF",
              "USD",
              "EUR",
              "GBP",
              "CNY",
              "NGN",
              "GHS",
              "KES",
              "ZAR"
            ],
            "default": "XAF",
            "description": "ISO 4217 currency code. Default is XAF (Central African CFA Franc)."
          },
          "type": {
            "type": "string",
            "enum": [
              "debit",
              "credit"
            ]
          },
          "description": {
            "type": "string",
            "example": "Mobile Money transfer from 237650000000"
          },
          "balance_after": {
            "type": "string",
            "pattern": "^[0-9]{1,15}(\\.[0-9]{1,4})?$",
            "description": "Account balance after this transaction, as a decimal string to avoid floating-point precision issues.",
            "example": "1475000"
          },
          "booking_date": {
            "type": "string",
            "format": "date"
          },
          "value_date": {
            "type": "string",
            "format": "date"
          },
          "timestamp": {
            "type": "string",
            "format": "date-time"
          },
          "AccountId": {
            "type": "string",
            "description": "OBIE alias for the account identifier. Maps to account_id in parent resource context. Deprecated on the primary Transaction schema — use TransactionOBIE for OBIE Read/Write Data API v3.1 consumers.",
            "deprecated": true,
            "x-replacement": "TransactionOBIE.AccountId"
          },
          "TransactionId": {
            "type": "string",
            "description": "OBIE alias for transaction_id. Deprecated on the primary Transaction schema — use TransactionOBIE for OBIE Read/Write Data API v3.1 consumers.",
            "deprecated": true,
            "x-replacement": "TransactionOBIE.TransactionId"
          },
          "Amount": {
            "type": "string",
            "pattern": "^[0-9]{1,15}$",
            "description": "OBIE alias for amount. Deprecated on the primary Transaction schema — use TransactionOBIE for OBIE Read/Write Data API v3.1 consumers.",
            "deprecated": true,
            "x-replacement": "TransactionOBIE.Amount"
          },
          "Currency": {
            "type": "string",
            "enum": [
              "XAF",
              "XOF",
              "USD",
              "EUR",
              "GBP",
              "CNY",
              "NGN",
              "GHS",
              "KES",
              "ZAR"
            ],
            "description": "OBIE alias for currency. Deprecated on the primary Transaction schema — use TransactionOBIE for OBIE Read/Write Data API v3.1 consumers.",
            "deprecated": true,
            "x-replacement": "TransactionOBIE.Currency"
          },
          "CreditDebitIndicator": {
            "type": "string",
            "enum": [
              "Credit",
              "Debit"
            ],
            "description": "OBIE alias for type. Maps credit/debit to transaction direction. Deprecated on the primary Transaction schema — use TransactionOBIE for OBIE Read/Write Data API v3.1 consumers.",
            "deprecated": true,
            "x-replacement": "TransactionOBIE.CreditDebitIndicator"
          },
          "BookingDateTime": {
            "type": "string",
            "format": "date-time",
            "description": "OBIE alias for booking_date. Deprecated on the primary Transaction schema — use TransactionOBIE for OBIE Read/Write Data API v3.1 consumers.",
            "deprecated": true,
            "x-replacement": "TransactionOBIE.BookingDateTime"
          },
          "ValueDateTime": {
            "type": "string",
            "format": "date-time",
            "description": "OBIE alias for value_date. Deprecated on the primary Transaction schema — use TransactionOBIE for OBIE Read/Write Data API v3.1 consumers.",
            "deprecated": true,
            "x-replacement": "TransactionOBIE.ValueDateTime"
          },
          "TransactionInformation": {
            "type": "string",
            "maxLength": 500,
            "description": "OBIE OBTransaction6 alias for the description field. Narrative text conveying information from the originator to the beneficiary about the payment transaction. Deprecated on the primary Transaction schema — use TransactionOBIE for OBIE Read/Write Data API v3.1 consumers.",
            "example": "Payment for Invoice INV-2025-001 — Professional Services",
            "deprecated": true,
            "x-replacement": "TransactionOBIE.TransactionInformation"
          },
          "Status": {
            "type": "string",
            "enum": [
              "Booked",
              "Pending",
              "Rejected"
            ],
            "description": "OBIE OBTransaction6 transaction status. Booked = settled, Pending = authorised but not yet settled, Rejected = declined or failed. Deprecated on the primary Transaction schema — use TransactionOBIE for OBIE Read/Write Data API v3.1 consumers.",
            "deprecated": true,
            "x-replacement": "TransactionOBIE.Status"
          }
        },
        "x-obie-mapping": {
          "AccountId": "account_id",
          "TransactionId": "transaction_id",
          "Amount": "amount",
          "Currency": "currency",
          "CreditDebitIndicator": "type",
          "BookingDateTime": "booking_date",
          "ValueDateTime": "value_date"
        },
        "required": [
          "transaction_id",
          "amount",
          "currency",
          "type",
          "timestamp"
        ],
        "x-naming-convention": "This schema uses dual naming: snake_case (native) and PascalCase (OBIE-compatible). Both represent the same field. SDK consumers should use snake_case. OBIE-conformant consumers may use PascalCase aliases. A future version will support content negotiation via Accept: application/json;profile=obie.",
        "description": "A booked or pending account transaction, including amount, currency, counterparty description and the resulting balance."
      },
      "Payment": {
        "type": "object",
        "properties": {
          "payment_id": {
            "type": "string",
            "format": "uuid"
          },
          "amount": {
            "type": "string",
            "example": "50000",
            "pattern": "^[0-9]{1,15}$",
            "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits). Must be consistent with the currency field."
          },
          "currency": {
            "type": "string",
            "default": "XAF",
            "enum": [
              "XAF",
              "XOF",
              "USD",
              "EUR",
              "GBP",
              "CNY",
              "NGN",
              "GHS",
              "KES",
              "ZAR"
            ],
            "description": "ISO 4217 currency code. Default is XAF (Central African CFA Franc)."
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "authorized",
              "submitted",
              "completed",
              "failed",
              "cancelled"
            ]
          },
          "debtor_account": {
            "type": "string",
            "example": "CM21 10003 00100 0123456789 023"
          },
          "creditor_account": {
            "type": "string",
            "example": "CM21 10003 00200 9876543210 045"
          },
          "reference": {
            "type": "string",
            "example": "Invoice-2026-001"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "payment_id",
          "amount",
          "currency",
          "status",
          "debtor_account",
          "creditor_account"
        ],
        "description": "A payment initiation resource describing the debtor account, creditor account, amount and current settlement status."
      },
      "Consent": {
        "type": "object",
        "properties": {
          "consent_id": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "AwaitingAuthorisation",
              "Authorised",
              "Rejected",
              "Consumed",
              "Expired",
              "Revoked"
            ]
          },
          "permissions": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "expiration_date": {
            "type": "string",
            "format": "date-time"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "consent_id",
          "status",
          "permissions",
          "expiration_date",
          "created_at"
        ],
        "description": "An account-access or payment consent granted by a user, listing the approved permissions and the expiry after which access stops."
      },
      "Bank": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "legal_name": {
            "type": "string",
            "example": "Afriland First Bank"
          },
          "display_name": {
            "type": "string"
          },
          "short_code": {
            "type": "string",
            "example": "AFB"
          },
          "country": {
            "type": "string",
            "default": "CM"
          },
          "swift_bic": {
            "type": "string",
            "example": "AFRIACMCXXX"
          },
          "bank_code": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "draft",
              "submitted",
              "active",
              "suspended"
            ]
          },
          "integration_mode": {
            "type": "string",
            "enum": [
              "connector_push",
              "connector_pull",
              "file_feed",
              "hybrid"
            ]
          },
          "contact_email": {
            "type": "string"
          },
          "support_phone": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "legal_name",
          "short_code",
          "country"
        ],
        "description": "A directory entry for a connected financial institution, including legal and display names, country, SWIFT/BIC and national bank code."
      },
      "InterbankPayment": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "external_reference": {
            "type": "string"
          },
          "debtor_participant_id": {
            "type": "string",
            "format": "uuid"
          },
          "creditor_participant_id": {
            "type": "string",
            "format": "uuid"
          },
          "amount": {
            "type": "string",
            "example": "500000",
            "pattern": "^[0-9]{1,15}$",
            "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits). Must be consistent with the currency field."
          },
          "currency": {
            "type": "string",
            "default": "XAF",
            "enum": [
              "XAF",
              "XOF",
              "USD",
              "EUR",
              "GBP",
              "CNY",
              "NGN",
              "GHS",
              "KES",
              "ZAR"
            ],
            "description": "ISO 4217 currency code. Default is XAF (Central African CFA Franc)."
          },
          "status": {
            "type": "string",
            "enum": [
              "created",
              "validated",
              "submitted",
              "accepted",
              "rejected",
              "in_process",
              "settled",
              "failed",
              "reversed",
              "expired"
            ]
          },
          "correlation_id": {
            "type": "string"
          },
          "requested_at": {
            "type": "string",
            "format": "date-time"
          },
          "settled_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "debtor_participant_id",
          "creditor_participant_id",
          "amount",
          "currency",
          "status"
        ],
        "description": "An interbank (ISO 20022) payment between two clearing participants, tracked by correlation identifier through its settlement lifecycle."
      },
      "Certificate": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "thumbprint": {
            "type": "string"
          },
          "fingerprint": {
            "type": "string"
          },
          "subject_dn": {
            "type": "string"
          },
          "issuer_dn": {
            "type": "string"
          },
          "serial_number": {
            "type": "string"
          },
          "valid_from": {
            "type": "string",
            "format": "date-time"
          },
          "valid_until": {
            "type": "string",
            "format": "date-time"
          },
          "is_revoked": {
            "type": "boolean"
          }
        },
        "required": [
          "id",
          "thumbprint",
          "subject_dn",
          "issuer_dn"
        ],
        "description": "An X.509 certificate registered for mutual TLS or message signing, with subject, issuer, serial number and validity window."
      },
      "CreditScore": {
        "type": "object",
        "properties": {
          "score": {
            "type": "integer",
            "minimum": 300,
            "maximum": 850,
            "example": 680
          },
          "grade": {
            "type": "string",
            "enum": [
              "A",
              "B",
              "C",
              "D",
              "F"
            ]
          },
          "score_range": {
            "type": "string",
            "enum": [
              "Poor",
              "Fair",
              "Good",
              "Very Good",
              "Excellent"
            ]
          },
          "calculated_at": {
            "type": "string",
            "format": "date-time"
          },
          "data_sources": {
            "type": "array",
            "description": "Inputs combined to produce this score. CEMAC deployments fold in mobile-money history, njangi (tontine) participation, and the COBAC Centrale des Risques registry alongside conventional bureau data.",
            "items": {
              "type": "string",
              "enum": [
                "mobile_money_history",
                "bank_transactions",
                "utility_payments",
                "njangi_participation",
                "merchant_sales",
                "bureau_creditinfo",
                "cobac_registry",
                "agent_float_history"
              ]
            },
            "example": [
              "mobile_money_history",
              "njangi_participation",
              "cobac_registry"
            ]
          },
          "locale_band": {
            "type": "string",
            "enum": [
              "cemac_v1",
              "fico_us",
              "experian_eu"
            ],
            "default": "cemac_v1",
            "description": "Scoring band semantics. The 300-850 scale is shared but A-F grade cutoffs differ per band.",
            "example": "cemac_v1"
          }
        },
        "required": [
          "score",
          "grade",
          "calculated_at"
        ],
        "description": "A calculated credit score for a subject, expressed on the platform 300–850 range with its grade, contributing data sources and locale band."
      },
      "LoanApplication": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "product_id": {
            "type": "string",
            "format": "uuid"
          },
          "amount": {
            "type": "string",
            "example": "1000000",
            "pattern": "^[0-9]{1,15}$",
            "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits). Must be consistent with the currency field."
          },
          "currency": {
            "type": "string",
            "example": "XAF",
            "enum": [
              "XAF",
              "XOF",
              "USD",
              "EUR",
              "GBP",
              "CNY",
              "NGN",
              "GHS",
              "KES",
              "ZAR"
            ],
            "default": "XAF",
            "description": "ISO 4217 currency code. Default is XAF (Central African CFA Franc)."
          },
          "term_months": {
            "type": "integer",
            "example": 12
          },
          "interest_rate": {
            "type": "number",
            "example": 15
          },
          "status": {
            "type": "string",
            "enum": [
              "applied",
              "under_review",
              "approved",
              "rejected",
              "disbursed",
              "active",
              "completed",
              "defaulted",
              "written_off"
            ]
          },
          "purpose": {
            "type": "string",
            "example": "Business expansion"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "product_id",
          "amount",
          "currency",
          "term_months",
          "status"
        ],
        "description": "A loan application, capturing the requested product, principal, term, interest rate, purpose and current decision status."
      },
      "LoanScheduleItem": {
        "type": "object",
        "properties": {
          "installment_number": {
            "type": "integer",
            "example": 1
          },
          "due_date": {
            "type": "string",
            "format": "date",
            "example": "2026-03-16"
          },
          "principal": {
            "type": "number",
            "example": 80000,
            "deprecated": true,
            "description": "Deprecated. Floating-point amount. Use `principal_amount` (string, minor units) instead. Will be removed in v5.0.0. [DEPRECATED — removal in v5.0.0. Use `principal_amount` (zero-decimal string, ^[0-9]{1,15}$).]\n\nDeprecated: floating-point monetary value (IEEE-754 binary64 cannot represent decimal minor units exactly). Use `principal_money` instead. Removal is scheduled for v5.0.0.",
            "x-successor": "principal_money",
            "x-sunset": "5.0.0"
          },
          "interest": {
            "type": "number",
            "example": 12500,
            "deprecated": true,
            "description": "Deprecated. Floating-point amount. Use `interest_amount` (string, minor units) instead. Will be removed in v5.0.0. [DEPRECATED — removal in v5.0.0. Use `interest_amount` (zero-decimal string, ^[0-9]{1,15}$).]\n\nDeprecated: floating-point monetary value (IEEE-754 binary64 cannot represent decimal minor units exactly). Use `interest_money` instead. Removal is scheduled for v5.0.0.",
            "x-successor": "interest_money",
            "x-sunset": "5.0.0"
          },
          "fees": {
            "type": "number",
            "example": 0,
            "deprecated": true,
            "description": "Deprecated. Floating-point amount. Use `fees_amount` (string, minor units) instead. Will be removed in v5.0.0.\n\nDeprecated: floating-point monetary value (IEEE-754 binary64 cannot represent decimal minor units exactly). Use `fees_money` instead. Removal is scheduled for v5.0.0.",
            "x-successor": "fees_money",
            "x-sunset": "5.0.0"
          },
          "total_due": {
            "type": "number",
            "example": 92500,
            "deprecated": true,
            "description": "Deprecated. Floating-point amount. Use `total_due_amount` (string, minor units) instead. Will be removed in v5.0.0. [DEPRECATED — removal in v5.0.0. Use `total_due_amount` (zero-decimal string, ^[0-9]{1,15}$).]\n\nDeprecated: floating-point monetary value (IEEE-754 binary64 cannot represent decimal minor units exactly). Use `total_due_money` instead. Removal is scheduled for v5.0.0.",
            "x-successor": "total_due_money",
            "x-sunset": "5.0.0"
          },
          "outstanding_balance": {
            "type": "string",
            "example": "920000",
            "pattern": "^[0-9]{1,15}$",
            "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits)."
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "paid",
              "partial",
              "overdue"
            ]
          },
          "principal_amount": {
            "type": "string",
            "pattern": "^[0-9]{1,15}$",
            "example": "80000",
            "description": "String integer amount in minor units. Replaces `principal`."
          },
          "interest_amount": {
            "type": "string",
            "pattern": "^[0-9]{1,15}$",
            "example": "80000",
            "description": "String integer amount in minor units. Replaces `interest`."
          },
          "fees_amount": {
            "type": "string",
            "pattern": "^[0-9]{1,15}$",
            "example": "80000",
            "description": "String integer amount in minor units. Replaces `fees`."
          },
          "total_due_amount": {
            "type": "string",
            "pattern": "^[0-9]{1,15}$",
            "example": "80000",
            "description": "String integer amount in minor units. Replaces `total_due`."
          },
          "principal_money": {
            "$ref": "#/components/schemas/Money",
            "description": "Canonical string-encoded successor to `principal`. Amount and ISO 4217 currency travel together (ISO 20022 ActiveCurrencyAndAmount). Prefer this field: it is exact for zero-decimal currencies (XAF, XOF) and immune to IEEE-754 drift.",
            "x-added-in": "4.54.0"
          },
          "interest_money": {
            "$ref": "#/components/schemas/Money",
            "description": "Canonical string-encoded successor to `interest`. Amount and ISO 4217 currency travel together (ISO 20022 ActiveCurrencyAndAmount). Prefer this field: it is exact for zero-decimal currencies (XAF, XOF) and immune to IEEE-754 drift.",
            "x-added-in": "4.54.0"
          },
          "fees_money": {
            "$ref": "#/components/schemas/Money",
            "description": "Canonical string-encoded successor to `fees`. Amount and ISO 4217 currency travel together (ISO 20022 ActiveCurrencyAndAmount). Prefer this field: it is exact for zero-decimal currencies (XAF, XOF) and immune to IEEE-754 drift.",
            "x-added-in": "4.54.0"
          },
          "total_due_money": {
            "$ref": "#/components/schemas/Money",
            "description": "Canonical string-encoded successor to `total_due`. Amount and ISO 4217 currency travel together (ISO 20022 ActiveCurrencyAndAmount). Prefer this field: it is exact for zero-decimal currencies (XAF, XOF) and immune to IEEE-754 drift.",
            "x-added-in": "4.54.0"
          }
        },
        "required": [
          "installment_number",
          "due_date",
          "principal_amount",
          "interest_amount",
          "total_due_amount"
        ],
        "x-deprecation": {
          "deprecated_fields": [
            "principal",
            "interest",
            "total_due"
          ],
          "removal_version": "5.0.0",
          "replacement_fields": {
            "principal": "principal_amount",
            "interest": "interest_amount",
            "total_due": "total_due_amount"
          },
          "migration_guide_url": "https://kangopenbanking.com/developer/changelog#loan-schedule-item-numeric-fields",
          "cited_standards": [
            "RFC 6648 §3",
            "draft-ietf-httpapi-deprecation-header-02"
          ]
        },
        "description": "A single instalment on a loan repayment schedule, splitting the amount due into principal, interest and fees."
      },
      "SavingsAccount": {
        "type": "object",
        "description": "Savings account resource",
        "properties": {
          "account_id": {
            "type": "string",
            "format": "uuid"
          },
          "product_id": {
            "type": "string",
            "description": "Savings product reference"
          },
          "account_number": {
            "type": "string"
          },
          "account_holder_name": {
            "type": "string"
          },
          "balance": {
            "type": "string",
            "pattern": "^[0-9]{1,15}$",
            "description": "Current balance in minor units"
          },
          "currency": {
            "type": "string",
            "enum": [
              "XAF",
              "XOF",
              "USD",
              "EUR"
            ],
            "default": "XAF"
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "dormant",
              "closed",
              "frozen"
            ]
          },
          "interest_rate": {
            "type": "number",
            "description": "Annual interest rate as a decimal (e.g. 0.045 = 4.5%)"
          },
          "opened_date": {
            "type": "string",
            "format": "date"
          },
          "maturity_date": {
            "type": "string",
            "format": "date"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "account_id",
          "balance",
          "currency",
          "status"
        ]
      },
      "LedgerAccount": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "code": {
            "type": "string",
            "example": "1000"
          },
          "name": {
            "type": "string",
            "example": "Cash and Cash Equivalents"
          },
          "account_type": {
            "type": "string",
            "enum": [
              "asset",
              "liability",
              "equity",
              "revenue",
              "expense"
            ]
          },
          "currency": {
            "type": "string",
            "example": "XAF",
            "enum": [
              "XAF",
              "XOF",
              "USD",
              "EUR",
              "GBP",
              "CNY",
              "NGN",
              "GHS",
              "KES",
              "ZAR"
            ],
            "default": "XAF",
            "description": "ISO 4217 currency code. Default is XAF (Central African CFA Franc)."
          },
          "balance": {
            "type": "string",
            "example": "25000000",
            "pattern": "^[0-9]{1,15}$",
            "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits). Must be consistent with the currency field."
          },
          "is_active": {
            "type": "boolean"
          }
        },
        "required": [
          "id",
          "code",
          "name",
          "account_type",
          "currency"
        ],
        "description": "A double-entry ledger account: its code, name, account type, currency and current balance."
      },
      "JournalEntry": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "readOnly": true,
            "description": "Server-generated journal entry identifier."
          },
          "entry_date": {
            "type": "string",
            "format": "date"
          },
          "description": {
            "type": "string",
            "example": "Loan disbursement - APP-2026-001"
          },
          "reference_type": {
            "type": "string",
            "enum": [
              "payment",
              "loan",
              "savings",
              "fee",
              "interest",
              "manual"
            ]
          },
          "reference_id": {
            "type": "string",
            "format": "uuid"
          },
          "lines": {
            "type": "array",
            "minItems": 2,
            "description": "Balanced set of posted journal lines.",
            "items": {
              "$ref": "#/components/schemas/JournalLine"
            }
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "readOnly": true,
            "description": "Server-generated creation timestamp (UTC, RFC 3339)."
          }
        },
        "required": [
          "id",
          "entry_date",
          "description",
          "reference_type",
          "reference_id",
          "lines"
        ],
        "description": "A double-entry journal entry with its balanced debit and credit lines and the business reference that produced it."
      },
      "MobileMoneyCharge": {
        "type": "object",
        "properties": {
          "transaction_id": {
            "type": "string"
          },
          "phone_number": {
            "type": "string",
            "example": "237650000000"
          },
          "amount": {
            "type": "string",
            "example": "5000",
            "pattern": "^[0-9]{1,15}$",
            "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits). Must be consistent with the currency field."
          },
          "currency": {
            "type": "string",
            "default": "XAF",
            "enum": [
              "XAF",
              "XOF",
              "USD",
              "EUR",
              "GBP",
              "CNY",
              "NGN",
              "GHS",
              "KES",
              "ZAR"
            ],
            "description": "ISO 4217 currency code. Default is XAF (Central African CFA Franc)."
          },
          "provider": {
            "type": "string",
            "enum": [
              "MTN",
              "Orange",
              "Airtel",
              "ExpressUnion",
              "CamPost"
            ],
            "description": "Mobile-money provider. CEMAC-wide coverage: MTN MoMo (CM/CG/CI), Orange Money (CM/CI/SN/ML), Airtel Money (TD/CG/CD/RW/ZM/MW), Express Union (CM cash-pickup), CamPost (CM postal financial services). See GSMA MMA v1.2 §4.2."
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "completed",
              "failed"
            ]
          }
        },
        "required": [
          "transaction_id",
          "phone_number",
          "amount",
          "currency",
          "provider",
          "status"
        ],
        "description": "A mobile-money collection request against a subscriber MSISDN, with the provider handling the charge and its current status."
      },
      "VirtualCard": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "card_number_masked": {
            "type": "string",
            "example": "**** **** **** 1234",
            "x-pci-scope": "masked_pan_only",
            "description": "Truncated PAN per PCI DSS req 3.3 (first 6 / last 4 maximum). Safe for storage, logs, and UI."
          },
          "balance_usd": {
            "type": "number",
            "example": 100,
            "deprecated": true,
            "description": "Deprecated. Floating-point representation of USD balance. Use `balance` (string, minor units) and `currency` instead. Will be removed in v5.0.0.\n\nDeprecated: floating-point monetary value (IEEE-754 binary64 cannot represent decimal minor units exactly). Use `balance_usd_money` instead. Removal is scheduled for v5.0.0.",
            "x-successor": "balance_usd_money",
            "x-sunset": "5.0.0"
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "frozen",
              "cancelled"
            ]
          },
          "expiry_month": {
            "type": "integer"
          },
          "expiry_year": {
            "type": "integer"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "balance": {
            "type": "string",
            "pattern": "^[0-9]{1,15}$",
            "example": "10000",
            "description": "Card balance as a string integer in the currency's minor unit (e.g. cents for USD). Replaces balance_usd."
          },
          "currency": {
            "type": "string",
            "enum": [
              "USD",
              "XAF",
              "EUR",
              "GBP"
            ],
            "default": "USD",
            "example": "USD",
            "description": "ISO 4217 currency code for the balance."
          },
          "balance_usd_money": {
            "$ref": "#/components/schemas/Money",
            "description": "Canonical string-encoded successor to `balance_usd`. Amount and ISO 4217 currency travel together (ISO 20022 ActiveCurrencyAndAmount). Prefer this field: it is exact for zero-decimal currencies (XAF, XOF) and immune to IEEE-754 drift.",
            "x-added-in": "4.54.0"
          }
        },
        "required": [
          "id",
          "card_number_masked",
          "status"
        ],
        "description": "An issued virtual card. The card number is always returned masked; full PAN and CVV are available only through the step-up reveal operation."
      },
      "WebhookEventType": {
        "type": "object",
        "description": "Webhook event type with its payload structure. All webhook deliveries follow the WebhookEventPayload envelope with event-type-specific data.",
        "allOf": [
          {
            "$ref": "#/components/schemas/WebhookEventPayload"
          }
        ],
        "properties": {
          "event": {
            "type": "string",
            "enum": [
              "wildcard.*",
              "charge.created",
              "charge.captured",
              "charge.voided",
              "charge.failed",
              "charge.cancelled",
              "refund.created",
              "refund.processed",
              "refund.failed",
              "payout.created",
              "payout.processing",
              "payout.completed",
              "payout.failed",
              "payment.initiated",
              "payment.authorised",
              "payment.submitted",
              "payment.completed",
              "payment.rejected",
              "payment.cancelled",
              "dispute.created",
              "dispute.evidence_required",
              "dispute.resolved",
              "settlement.created",
              "settlement.processed",
              "consent.authorised",
              "consent.revoked",
              "consent.expired",
              "loan.applied",
              "loan.approved",
              "loan.disbursed",
              "loan.repaid",
              "loan.defaulted",
              "kyc.submitted",
              "kyc.approved",
              "kyc.rejected",
              "mobile_money.charge_initiated",
              "mobile_money.charge_completed",
              "mobile_money.charge_failed",
              "escrow.funded",
              "escrow.released",
              "escrow.refunded",
              "virtual_account.credited",
              "interbank.payment_submitted",
              "interbank.payment_completed",
              "interbank.payment_returned",
              "pay_by_bank.intent_authorised",
              "pay_by_bank.intent_rejected",
              "pay_by_bank.payment_completed",
              "subscription.created",
              "subscription.renewed",
              "subscription.cancelled",
              "subscription.payment_failed"
            ],
            "description": "The specific event type. Use 'wildcard.*' to subscribe to all events."
          },
          "data": {
            "type": "object",
            "description": "Event-specific payload. Key schemas by event: charge.* -> GatewayCharge, refund.* -> GatewayRefund, payout.* -> GatewayPayout, payment.* -> Payment, dispute.* -> GatewayDispute, settlement.* -> GatewaySettlement, consent.* -> Consent, loan.* -> LoanApplication, mobile_money.* -> MobileMoneyCharge, interbank.* -> InterbankPayment, pay_by_bank.* -> PayByBankIntent, subscription.* -> GatewaySubscription",
            "additionalProperties": true
          },
          "type": {
            "type": "string",
            "description": "Required field — added in v4.27.3."
          },
          "version": {
            "type": "string",
            "description": "Required field — added in v4.27.3."
          }
        },
        "required": [
          "type",
          "version"
        ]
      },
      "Webhook": {
        "type": "object",
        "properties": {
          "webhook_id": {
            "type": "string",
            "format": "uuid"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "events": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebhookEventType"
            }
          },
          "is_active": {
            "type": "boolean"
          },
          "secret": {
            "type": "string",
            "description": "HMAC signing secret (shown only once)"
          }
        },
        "required": [
          "webhook_id",
          "url",
          "events",
          "is_active"
        ],
        "description": "A registered webhook endpoint: the destination URL, subscribed event types, activation state and the secret used to sign deliveries."
      },
      "HealthStatus": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "healthy",
              "degraded",
              "unhealthy"
            ]
          },
          "version": {
            "type": "string",
            "example": "1.0.0"
          },
          "timestamp": {
            "type": "string",
            "format": "date-time"
          },
          "services": {
            "type": "object",
            "additionalProperties": {
              "type": "object",
              "properties": {
                "status": {
                  "type": "string"
                },
                "latency_ms": {
                  "type": "integer"
                }
              }
            }
          }
        },
        "required": [
          "status",
          "version",
          "timestamp"
        ],
        "description": "A service health probe result reporting overall status, deployed version, timestamp and per-dependency availability."
      },
      "GatewayCharge": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "merchant_id": {
            "type": "string",
            "format": "uuid"
          },
          "amount": {
            "type": "string",
            "example": "5000",
            "pattern": "^[0-9]{1,15}$",
            "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits). Must be consistent with the currency field."
          },
          "currency": {
            "type": "string",
            "example": "XAF",
            "enum": [
              "XAF",
              "XOF",
              "USD",
              "EUR",
              "GBP",
              "CNY",
              "NGN",
              "GHS",
              "KES",
              "ZAR"
            ],
            "default": "XAF",
            "description": "ISO 4217 currency code. Default is XAF (Central African CFA Franc)."
          },
          "channel": {
            "type": "string",
            "enum": [
              "mobile_money",
              "card",
              "bank_transfer",
              "apple_pay",
              "google_pay",
              "ussd",
              "paypal"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "processing",
              "successful",
              "failed",
              "cancelled",
              "authorized",
              "voided"
            ]
          },
          "provider": {
            "type": "string",
            "enum": [
              "flutterwave",
              "stripe",
              "paypal"
            ]
          },
          "provider_ref": {
            "type": "string"
          },
          "fee_amount": {
            "type": "string",
            "example": "200",
            "pattern": "^-?[0-9]{1,15}$",
            "format": "monetary-minor-unit",
            "x-coercion": "numeric→string in v4.29.0 per FAPI 1.0 Adv §5.2.2 / RFC 8259 precision"
          },
          "net_amount": {
            "type": "string",
            "example": "4800",
            "pattern": "^-?[0-9]{1,15}$",
            "format": "monetary-minor-unit",
            "x-coercion": "numeric→string in v4.29.0 per FAPI 1.0 Adv §5.2.2 / RFC 8259 precision"
          },
          "tx_ref": {
            "type": "string"
          },
          "customer_phone": {
            "type": "string"
          },
          "customer_email": {
            "type": "string"
          },
          "capture_mode": {
            "type": "string",
            "enum": [
              "auto",
              "manual"
            ],
            "default": "auto"
          },
          "captured_amount": {
            "type": "number",
            "example": 0,
            "deprecated": true,
            "x-successor": "captured_amount_money",
            "x-sunset": "5.0.0",
            "description": "Deprecated: floating-point monetary value (IEEE-754 binary64 cannot represent decimal minor units exactly). Use `captured_amount_money` instead. Removal is scheduled for v5.0.0."
          },
          "fee_bearer": {
            "type": "string",
            "enum": [
              "merchant",
              "customer"
            ],
            "default": "merchant"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "description": "Timestamp of last status change"
          },
          "description": {
            "type": "string",
            "description": "Merchant-provided description of the charge"
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Arbitrary key-value metadata attached to this charge by the merchant"
          },
          "customer_id": {
            "type": "string",
            "description": "Identifier of the customer associated with this charge"
          },
          "dispute_id": {
            "type": "string",
            "format": "uuid",
            "description": "ID of the dispute if this charge has been disputed"
          },
          "refunded_at": {
            "type": "string",
            "format": "date-time",
            "description": "Timestamp when the charge was fully refunded, if applicable"
          },
          "failure_reason": {
            "type": "string",
            "description": "Machine-readable failure reason code (e.g. insufficient_funds, expired_card)"
          },
          "failure_message": {
            "type": "string",
            "description": "Human-readable failure message for display to the merchant"
          },
          "captured_amount_money": {
            "$ref": "#/components/schemas/Money",
            "description": "Canonical string-encoded successor to `captured_amount`. Amount and ISO 4217 currency travel together (ISO 20022 ActiveCurrencyAndAmount). Prefer this field: it is exact for zero-decimal currencies (XAF, XOF) and immune to IEEE-754 drift.",
            "x-added-in": "4.54.0"
          }
        },
        "required": [
          "id",
          "merchant_id",
          "amount",
          "currency",
          "channel",
          "status",
          "created_at"
        ],
        "description": "A payment gateway charge: the amount collected from a payer through a given channel and provider, with its current authorisation and settlement status."
      },
      "GatewayPayout": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "merchant_id": {
            "type": "string",
            "format": "uuid"
          },
          "amount": {
            "type": "string",
            "example": "10000",
            "pattern": "^[0-9]{1,15}$",
            "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits). Must be consistent with the currency field."
          },
          "currency": {
            "type": "string",
            "example": "XAF",
            "enum": [
              "XAF",
              "XOF",
              "USD",
              "EUR",
              "GBP",
              "CNY",
              "NGN",
              "GHS",
              "KES",
              "ZAR"
            ],
            "default": "XAF",
            "description": "ISO 4217 currency code. Default is XAF (Central African CFA Franc)."
          },
          "channel": {
            "type": "string",
            "enum": [
              "mobile_money",
              "bank_transfer",
              "paypal"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "processing",
              "completed",
              "failed"
            ]
          },
          "beneficiary_name": {
            "type": "string"
          },
          "beneficiary_phone": {
            "type": "string"
          },
          "tx_ref": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "merchant_id",
          "amount",
          "currency",
          "channel",
          "status",
          "created_at"
        ],
        "description": "A payout instructing funds out of a merchant balance to a beneficiary over the selected disbursement channel."
      },
      "GatewayRefund": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "charge_id": {
            "type": "string",
            "format": "uuid"
          },
          "amount": {
            "type": "string",
            "example": "5000",
            "pattern": "^[0-9]{1,15}$",
            "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits). Must be consistent with the currency field."
          },
          "currency": {
            "type": "string",
            "example": "XAF",
            "enum": [
              "XAF",
              "XOF",
              "USD",
              "EUR",
              "GBP",
              "CNY",
              "NGN",
              "GHS",
              "KES",
              "ZAR"
            ],
            "default": "XAF",
            "description": "ISO 4217 currency code. Default is XAF (Central African CFA Franc)."
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "processing",
              "completed",
              "failed"
            ]
          },
          "provider": {
            "type": "string"
          },
          "reason": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "charge_id",
          "amount",
          "currency",
          "status"
        ],
        "description": "A full or partial refund raised against an existing charge, with the reason and the provider processing it."
      },
      "GatewayDispute": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "charge_id": {
            "type": "string",
            "format": "uuid"
          },
          "amount": {
            "type": "string",
            "example": "5000",
            "pattern": "^[0-9]{1,15}$",
            "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits). Must be consistent with the currency field."
          },
          "currency": {
            "type": "string",
            "example": "XAF",
            "enum": [
              "XAF",
              "XOF",
              "USD",
              "EUR",
              "GBP",
              "CNY",
              "NGN",
              "GHS",
              "KES",
              "ZAR"
            ],
            "default": "XAF",
            "description": "ISO 4217 currency code. Default is XAF (Central African CFA Franc)."
          },
          "status": {
            "type": "string",
            "enum": [
              "open",
              "under_review",
              "won",
              "lost",
              "closed"
            ]
          },
          "reason": {
            "type": "string"
          },
          "evidence_due_by": {
            "type": "string",
            "format": "date-time"
          },
          "provider": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "charge_id",
          "amount",
          "currency",
          "status"
        ],
        "description": "A chargeback or dispute raised against a charge, including the reason, disputed amount and the evidence submission deadline."
      },
      "GatewaySettlement": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "merchant_id": {
            "type": "string",
            "format": "uuid"
          },
          "amount": {
            "type": "string",
            "example": "450000",
            "pattern": "^[0-9]{1,15}$",
            "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits). Must be consistent with the currency field."
          },
          "currency": {
            "type": "string",
            "example": "XAF",
            "enum": [
              "XAF",
              "XOF",
              "USD",
              "EUR",
              "GBP",
              "CNY",
              "NGN",
              "GHS",
              "KES",
              "ZAR"
            ],
            "default": "XAF",
            "description": "ISO 4217 currency code. Default is XAF (Central African CFA Franc)."
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "processing",
              "paid"
            ]
          },
          "period_start": {
            "type": "string",
            "format": "date"
          },
          "period_end": {
            "type": "string",
            "format": "date"
          },
          "charges_count": {
            "type": "integer"
          },
          "fees_total": {
            "type": "number",
            "deprecated": true,
            "x-successor": "fees_total_money",
            "x-sunset": "5.0.0",
            "description": "Deprecated: floating-point monetary value (IEEE-754 binary64 cannot represent decimal minor units exactly). Use `fees_total_money` instead. Removal is scheduled for v5.0.0."
          },
          "net_amount": {
            "type": "string",
            "pattern": "^-?[0-9]{1,15}$",
            "format": "monetary-minor-unit",
            "example": "0",
            "x-coercion": "numeric→string in v4.29.0 per FAPI 1.0 Adv §5.2.2 / RFC 8259 precision"
          },
          "settled_at": {
            "type": "string",
            "format": "date-time"
          },
          "fees_total_money": {
            "$ref": "#/components/schemas/Money",
            "description": "Canonical string-encoded successor to `fees_total`. Amount and ISO 4217 currency travel together (ISO 20022 ActiveCurrencyAndAmount). Prefer this field: it is exact for zero-decimal currencies (XAF, XOF) and immune to IEEE-754 drift.",
            "x-added-in": "4.54.0"
          }
        },
        "required": [
          "id",
          "merchant_id",
          "amount",
          "currency",
          "status"
        ],
        "description": "A settlement batch paying a merchant for a closed period, summarising the charges and net amount included."
      },
      "GatewayBeneficiary": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "merchant_id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "channel": {
            "type": "string",
            "enum": [
              "mobile_money",
              "bank_transfer"
            ]
          },
          "phone": {
            "type": "string"
          },
          "bank_account": {
            "type": "string"
          },
          "bank_code": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "merchant_id",
          "name",
          "channel"
        ],
        "description": "A saved payout destination for a merchant — either a mobile-money MSISDN or a bank account with its bank code."
      },
      "GatewayFeeEstimate": {
        "type": "object",
        "properties": {
          "amount": {
            "type": "string",
            "example": "5000",
            "pattern": "^[0-9]{1,15}$",
            "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits). Must be consistent with the currency field."
          },
          "currency": {
            "type": "string",
            "example": "XAF",
            "enum": [
              "XAF",
              "XOF",
              "USD",
              "EUR",
              "GBP",
              "CNY",
              "NGN",
              "GHS",
              "KES",
              "ZAR"
            ],
            "default": "XAF",
            "description": "ISO 4217 currency code. Default is XAF (Central African CFA Franc)."
          },
          "channel": {
            "type": "string"
          },
          "fee_amount": {
            "type": "string",
            "example": "200",
            "pattern": "^-?[0-9]{1,15}$",
            "format": "monetary-minor-unit",
            "x-coercion": "numeric→string in v4.29.0 per FAPI 1.0 Adv §5.2.2 / RFC 8259 precision"
          },
          "net_amount": {
            "type": "string",
            "example": "4800",
            "pattern": "^-?[0-9]{1,15}$",
            "format": "monetary-minor-unit",
            "x-coercion": "numeric→string in v4.29.0 per FAPI 1.0 Adv §5.2.2 / RFC 8259 precision"
          },
          "fee_percentage": {
            "type": "string",
            "example": "3%"
          },
          "fixed_fee": {
            "type": "string",
            "example": "50",
            "pattern": "^-?[0-9]{1,15}$",
            "format": "monetary-minor-unit",
            "x-coercion": "numeric→string in v4.29.0 per FAPI 1.0 Adv §5.2.2 / RFC 8259 precision"
          }
        },
        "required": [
          "amount",
          "currency",
          "channel",
          "fee_amount",
          "net_amount"
        ],
        "description": "A quoted fee breakdown for a prospective transaction, showing the percentage component, fixed component and the resulting net amount."
      },
      "GatewayVirtualAccount": {
        "type": "object",
        "description": "Nium-issued dedicated receiving account. account_kind=\"virtual\" returns local account coordinates; \"global\" returns IBAN/SWIFT details. All inbound funds auto-convert to XAF via the shared Nium FX engine.",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "merchant_id": {
            "type": "string",
            "format": "uuid"
          },
          "account_kind": {
            "type": "string",
            "enum": [
              "virtual",
              "global"
            ],
            "default": "virtual",
            "description": "Nium account class. Virtual = local rails; Global = IBAN/SWIFT receiving."
          },
          "account_number": {
            "type": "string",
            "example": "GB29NWBK60161331926819"
          },
          "iban": {
            "type": [
              "string",
              "null"
            ],
            "example": "GB29NWBK60161331926819"
          },
          "bic": {
            "type": [
              "string",
              "null"
            ],
            "example": "NWBKGB2L"
          },
          "routing_code": {
            "type": [
              "string",
              "null"
            ],
            "description": "Local clearing code (ABA, sort code, IFSC, BSB, etc.) when applicable."
          },
          "bank_name": {
            "type": "string",
            "example": "Citibank N.A. (via Nium)"
          },
          "bank_address": {
            "type": [
              "string",
              "null"
            ]
          },
          "beneficiary_name": {
            "type": "string",
            "description": "Must match the KYC-verified legal name."
          },
          "currency": {
            "type": "string",
            "enum": [
              "USD",
              "EUR",
              "GBP",
              "AUD",
              "CAD",
              "SGD",
              "AED",
              "JPY",
              "INR",
              "ZAR",
              "HKD",
              "CHF",
              "NZD",
              "SEK",
              "NOK",
              "DKK",
              "CNY",
              "XAF",
              "XOF",
              "NGN",
              "GHS",
              "KES"
            ],
            "example": "USD",
            "description": "Receiving currency. Funds settle to XAF by default."
          },
          "destination_currency": {
            "type": "string",
            "example": "XAF",
            "default": "XAF"
          },
          "provider": {
            "type": "string",
            "enum": [
              "nium"
            ],
            "default": "nium"
          },
          "mode": {
            "type": "string",
            "enum": [
              "stub",
              "sandbox",
              "live"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "suspended",
              "closed"
            ]
          },
          "email": {
            "type": "string"
          },
          "expiry": {
            "type": "string",
            "format": "date-time"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "bank_country": {
            "type": "string",
            "description": "ISO 3166-1 alpha-2 country code of the issuing bank.",
            "example": "CM"
          }
        },
        "required": [
          "id",
          "merchant_id",
          "account_number",
          "bank_name",
          "currency"
        ]
      },
      "GatewayMerchantWallet": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "merchant_id": {
            "type": "string",
            "format": "uuid"
          },
          "currency": {
            "type": "string",
            "example": "XAF",
            "enum": [
              "XAF",
              "XOF",
              "USD",
              "EUR",
              "GBP",
              "CNY",
              "NGN",
              "GHS",
              "KES",
              "ZAR"
            ],
            "default": "XAF",
            "description": "ISO 4217 currency code. Default is XAF (Central African CFA Franc)."
          },
          "available_balance": {
            "type": "string",
            "example": "500000",
            "pattern": "^[0-9]{1,15}$",
            "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits). Must be consistent with the currency field."
          },
          "pending_balance": {
            "type": "string",
            "example": "25000",
            "pattern": "^[0-9]{1,15}$",
            "description": "Represented as a string integer in the currency's minor unit, consistent with available_balance. Use string integers to preserve precision for zero-decimal currencies (XAF, XOF)."
          },
          "ledger_balance": {
            "type": "string",
            "example": "525000",
            "pattern": "^[0-9]{1,15}$",
            "description": "Represented as a string integer in the currency's minor unit, consistent with available_balance. Use string integers to preserve precision for zero-decimal currencies (XAF, XOF)."
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "merchant_id",
          "currency",
          "available_balance"
        ],
        "description": "A merchant balance in a single currency, split into available, pending and ledger balances."
      },
      "GatewayBankVerification": {
        "type": "object",
        "properties": {
          "account_name": {
            "type": "string",
            "example": "John Doe"
          },
          "account_number": {
            "type": "string",
            "example": "1234567890"
          }
        },
        "required": [
          "account_name",
          "account_number"
        ],
        "description": "The result of a bank account name-enquiry, returning the account holder name registered against the supplied account number."
      },
      "GatewayBvnResolution": {
        "type": "object",
        "properties": {
          "bvn": {
            "type": "string"
          },
          "first_name": {
            "type": "string"
          },
          "last_name": {
            "type": "string"
          },
          "middle_name": {
            "type": "string"
          },
          "date_of_birth": {
            "type": "string"
          },
          "phone_number": {
            "type": "string"
          }
        },
        "required": [
          "bvn",
          "first_name",
          "last_name"
        ],
        "description": "The identity attributes resolved for a Bank Verification Number lookup."
      },
      "GatewayPaymentLink": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "merchant_id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string",
            "example": "Product Payment"
          },
          "slug": {
            "type": "string",
            "example": "product-payment-abc123"
          },
          "amount": {
            "type": "string",
            "example": "5000",
            "pattern": "^[0-9]{1,15}$",
            "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits). Must be consistent with the currency field."
          },
          "currency": {
            "type": "string",
            "example": "XAF",
            "enum": [
              "XAF",
              "XOF",
              "USD",
              "EUR",
              "GBP",
              "CNY",
              "NGN",
              "GHS",
              "KES",
              "ZAR"
            ],
            "default": "XAF",
            "description": "ISO 4217 currency code. Default is XAF (Central African CFA Franc)."
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "inactive",
              "expired"
            ]
          },
          "redirect_url": {
            "type": "string"
          },
          "max_uses": {
            "type": "integer"
          },
          "use_count": {
            "type": "integer"
          },
          "expires_at": {
            "type": "string",
            "format": "date-time"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "merchant_id",
          "name",
          "slug",
          "amount",
          "currency",
          "status"
        ],
        "description": "A shareable hosted payment link, with its slug, optional fixed amount and post-payment redirect target."
      },
      "GatewayPaymentPlan": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "merchant_id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string",
            "example": "Monthly Pro Plan"
          },
          "amount": {
            "type": "string",
            "example": "10000",
            "pattern": "^[0-9]{1,15}$",
            "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits). Must be consistent with the currency field."
          },
          "currency": {
            "type": "string",
            "example": "XAF",
            "enum": [
              "XAF",
              "XOF",
              "USD",
              "EUR",
              "GBP",
              "CNY",
              "NGN",
              "GHS",
              "KES",
              "ZAR"
            ],
            "default": "XAF",
            "description": "ISO 4217 currency code. Default is XAF (Central African CFA Franc)."
          },
          "interval": {
            "type": "string",
            "enum": [
              "daily",
              "weekly",
              "monthly",
              "quarterly",
              "yearly"
            ]
          },
          "duration": {
            "type": "integer",
            "description": "Number of billing cycles (0 = unlimited)"
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "cancelled",
              "completed"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "merchant_id",
          "name",
          "amount",
          "currency"
        ],
        "description": "A recurring billing plan defining the amount, billing interval and duration used to create subscriptions."
      },
      "GatewaySubscription": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "plan_id": {
            "type": "string",
            "format": "uuid"
          },
          "customer_email": {
            "type": "string"
          },
          "customer_phone": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "paused",
              "cancelled",
              "completed",
              "past_due"
            ]
          },
          "current_period_start": {
            "type": "string",
            "format": "date-time"
          },
          "current_period_end": {
            "type": "string",
            "format": "date-time"
          },
          "next_charge_date": {
            "type": "string",
            "format": "date-time"
          },
          "charges_count": {
            "type": "integer"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "trial_start": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "UTC datetime when the trial period started. Null if no trial was applied to this subscription.",
            "example": "2025-03-01T00:00:00Z"
          },
          "trial_end": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "UTC datetime when the trial period ends or ended. After this datetime, regular billing resumes. Null if no trial was applied.",
            "example": "2025-03-15T00:00:00Z"
          },
          "cancel_at_period_end": {
            "type": "boolean",
            "default": false,
            "description": "When true, the subscription is scheduled to cancel at the end of the current billing period (current_period_end) rather than immediately. The status remains 'active' until then.",
            "example": false
          },
          "cancelled_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "UTC datetime when the subscription was cancelled (either immediately or when a scheduled end-of-period cancellation took effect). Null if subscription is still active.",
            "example": "2025-04-01T00:00:00Z"
          },
          "billing_cycle_anchor": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "UTC datetime that defines the billing cycle. Future billing dates are calculated relative to this anchor. Useful for aligning subscription billing to a fixed day of the month.",
            "example": "2025-01-01T00:00:00Z"
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "maxProperties": 20,
            "description": "Arbitrary key-value metadata attached to this subscription. Keys and values must be strings. Maximum 20 pairs.",
            "example": {
              "customer_ref": "CUST-001",
              "plan_tier": "professional"
            }
          }
        },
        "required": [
          "id",
          "plan_id",
          "status",
          "current_period_start",
          "current_period_end",
          "created_at"
        ],
        "description": "A customer subscription to a payment plan, tracking the current billing period and the next scheduled charge."
      },
      "GatewaySubaccount": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "merchant_id": {
            "type": "string",
            "format": "uuid"
          },
          "business_name": {
            "type": "string"
          },
          "settlement_bank": {
            "type": "string"
          },
          "account_number": {
            "type": "string"
          },
          "split_type": {
            "type": "string",
            "enum": [
              "percentage",
              "flat"
            ]
          },
          "split_value": {
            "type": "number"
          },
          "country": {
            "type": "string",
            "example": "CM"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "merchant_id",
          "business_name",
          "account_number"
        ],
        "description": "A marketplace subaccount receiving a percentage or fixed-amount split of charges, with its own settlement bank account."
      },
      "GatewayCustomer": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "merchant_id": {
            "type": "string",
            "format": "uuid"
          },
          "email": {
            "type": "string"
          },
          "phone": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "metadata": {
            "type": "object"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "merchant_id",
          "email"
        ],
        "description": "A merchant-scoped customer record used to attach charges, tokens and subscriptions to a single payer."
      },
      "GatewayCustomerToken": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "customer_id": {
            "type": "string",
            "format": "uuid"
          },
          "channel": {
            "type": "string",
            "enum": [
              "mobile_money",
              "card"
            ]
          },
          "token_ref": {
            "type": "string"
          },
          "last4": {
            "type": "string",
            "example": "1234"
          },
          "provider": {
            "type": "string"
          },
          "is_active": {
            "type": "boolean"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "customer_id",
          "channel",
          "token_ref"
        ],
        "description": "A reusable payment token stored against a customer so a payment instrument can be charged again without re-collecting details."
      },
      "GatewayChargeEvent": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "charge_id": {
            "type": "string",
            "format": "uuid"
          },
          "event_type": {
            "type": "string",
            "enum": [
              "charge.created",
              "charge.processing",
              "charge.successful",
              "charge.failed",
              "charge.cancelled",
              "charge.voided",
              "charge.captured",
              "charge.refunded"
            ],
            "example": "charge.created"
          },
          "data": {
            "type": "object"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "charge_id",
          "event_type",
          "created_at"
        ],
        "description": "An immutable lifecycle event emitted as a charge moves between states; the ordered event stream is the audit record for the charge."
      },
      "GatewayReconciliationRun": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "merchant_id": {
            "type": "string",
            "format": "uuid"
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "running",
              "completed",
              "failed"
            ]
          },
          "matched_count": {
            "type": "integer"
          },
          "mismatched_count": {
            "type": "integer"
          },
          "period_start": {
            "type": "string",
            "format": "date"
          },
          "period_end": {
            "type": "string",
            "format": "date"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "merchant_id",
          "status"
        ],
        "description": "A reconciliation run comparing platform records against a provider statement for a period, with the resulting match and exception counts."
      },
      "GatewayMerchant": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "user_id": {
            "type": "string",
            "format": "uuid"
          },
          "business_name": {
            "type": "string"
          },
          "business_type": {
            "type": "string"
          },
          "contact_email": {
            "type": "string"
          },
          "contact_phone": {
            "type": "string"
          },
          "country": {
            "type": "string",
            "example": "CM"
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "active",
              "suspended",
              "deactivated"
            ]
          },
          "kyb_status": {
            "type": "string",
            "enum": [
              "not_submitted",
              "pending",
              "approved",
              "rejected"
            ]
          },
          "logo_url": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "business_name",
          "business_type",
          "contact_email"
        ],
        "description": "A merchant account on the payment gateway, including its business identity, onboarding status and settlement configuration."
      },
      "WooCommerceMerchant": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "store_name": {
            "type": "string"
          },
          "store_url": {
            "type": "string",
            "format": "uri"
          },
          "admin_email": {
            "type": "string",
            "format": "email"
          },
          "api_key": {
            "type": "string",
            "description": "Generated API key for the merchant"
          },
          "client_secret": {
            "type": "string",
            "description": "Generated client secret (shown once)"
          },
          "webhook_secret": {
            "type": "string",
            "description": "Webhook signing secret"
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "inactive",
              "suspended"
            ]
          },
          "plugin_version": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "store_name",
          "store_url",
          "admin_email"
        ],
        "description": "A WooCommerce store connected to the gateway, linking the store URL and credentials to a platform merchant."
      },
      "WooCommerceTransaction": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "transaction_ref": {
            "type": "string"
          },
          "woocommerce_order_id": {
            "type": "integer"
          },
          "amount": {
            "type": "string",
            "pattern": "^[0-9]{1,15}$",
            "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits). Must be consistent with the currency field."
          },
          "currency": {
            "type": "string",
            "enum": [
              "XAF",
              "XOF",
              "USD",
              "EUR",
              "GBP",
              "CNY",
              "NGN",
              "GHS",
              "KES",
              "ZAR"
            ],
            "default": "XAF",
            "description": "ISO 4217 currency code. Default is XAF (Central African CFA Franc)."
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "completed",
              "failed",
              "refunded"
            ]
          },
          "payment_method": {
            "type": "string"
          },
          "customer_email": {
            "type": "string"
          },
          "fee_amount": {
            "type": "string",
            "pattern": "^-?[0-9]{1,15}$",
            "format": "monetary-minor-unit",
            "example": "0",
            "x-coercion": "numeric→string in v4.29.0 per FAPI 1.0 Adv §5.2.2 / RFC 8259 precision"
          },
          "net_amount": {
            "type": "string",
            "pattern": "^-?[0-9]{1,15}$",
            "format": "monetary-minor-unit",
            "example": "0",
            "x-coercion": "numeric→string in v4.29.0 per FAPI 1.0 Adv §5.2.2 / RFC 8259 precision"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "completed_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "transaction_ref",
          "amount",
          "currency",
          "status"
        ],
        "description": "A WooCommerce order payment as recorded by the gateway, linking the store order reference to the platform charge."
      },
      "PayByBankIntent": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "merchant_id": {
            "type": "string",
            "format": "uuid"
          },
          "consent_id": {
            "type": "string"
          },
          "amount": {
            "type": "string",
            "example": "50000",
            "pattern": "^[0-9]{1,15}$",
            "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits). Must be consistent with the currency field."
          },
          "currency": {
            "type": "string",
            "example": "XAF",
            "enum": [
              "XAF",
              "XOF",
              "USD",
              "EUR",
              "GBP",
              "CNY",
              "NGN",
              "GHS",
              "KES",
              "ZAR"
            ],
            "default": "XAF",
            "description": "ISO 4217 currency code. Default is XAF (Central African CFA Franc)."
          },
          "redirect_uri": {
            "type": "string",
            "format": "uri"
          },
          "state": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "awaiting_auth",
              "authorized",
              "submitted",
              "processing",
              "completed",
              "failed",
              "expired",
              "rejected"
            ]
          },
          "merchant_name": {
            "type": "string"
          },
          "merchant_logo_url": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri"
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "authorization_url": {
            "type": "string",
            "format": "uri"
          },
          "expires_at": {
            "type": "string",
            "format": "date-time"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "merchant_id",
          "amount",
          "currency",
          "status",
          "redirect_uri"
        ],
        "description": "A pay-by-bank intent: the bank-initiated payment a payer is asked to authorise, with its redirect and authorisation status."
      },
      "CreatePayByBankIntentRequest": {
        "type": "object",
        "required": [
          "merchant_id",
          "amount",
          "redirect_uri",
          "state"
        ],
        "properties": {
          "merchant_id": {
            "type": "string",
            "format": "uuid"
          },
          "amount": {
            "type": "string",
            "example": "50000",
            "pattern": "^[0-9]{1,15}$",
            "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits). Must be consistent with the currency field."
          },
          "currency": {
            "type": "string",
            "default": "XAF",
            "enum": [
              "XAF",
              "XOF",
              "USD",
              "EUR",
              "GBP",
              "CNY",
              "NGN",
              "GHS",
              "KES",
              "ZAR"
            ],
            "description": "ISO 4217 currency code. Default is XAF (Central African CFA Franc)."
          },
          "redirect_uri": {
            "type": "string",
            "format": "uri"
          },
          "state": {
            "type": "string",
            "description": "Opaque state for CSRF protection"
          },
          "description": {
            "type": "string"
          },
          "creditor_account": {
            "type": "string"
          },
          "creditor_name": {
            "type": "string"
          },
          "customer_email": {
            "type": "string",
            "format": "email"
          }
        },
        "description": "Request payload used to create a pay-by-bank intent for a payer."
      },
      "StandardResponse": {
        "type": "object",
        "description": "Unified single-resource response wrapper",
        "required": [
          "data",
          "meta"
        ],
        "properties": {
          "data": {
            "type": "object",
            "description": "The primary response payload"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        }
      },
      "PaginatedResponse": {
        "type": "object",
        "description": "Unified paginated list response wrapper",
        "required": [
          "data",
          "pagination",
          "meta"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {},
            "description": "Array of resource objects"
          },
          "pagination": {
            "$ref": "#/components/schemas/Pagination"
          },
          "meta": {
            "$ref": "#/components/schemas/ResponseMeta"
          }
        }
      },
      "ResponseMeta": {
        "type": "object",
        "description": "Standard response metadata",
        "required": [
          "request_id",
          "timestamp"
        ],
        "properties": {
          "request_id": {
            "type": "string",
            "format": "uuid",
            "description": "Unique request identifier (echoes x-fapi-interaction-id)",
            "example": "550e8400-e29b-41d4-a716-446655440000"
          },
          "timestamp": {
            "type": "string",
            "format": "date-time",
            "description": "UTC timestamp of the response",
            "example": "2025-03-27T12:00:00Z"
          },
          "api_version": {
            "type": "string",
            "description": "API version that served this response",
            "example": "4.3.0"
          }
        }
      },
      "ProblemDetails": {
        "type": "object",
        "description": "RFC 7807 Problem Details for HTTP APIs. Used for structured error responses.",
        "required": [
          "type",
          "title",
          "status"
        ],
        "properties": {
          "type": {
            "type": "string",
            "format": "uri",
            "description": "URI reference identifying the problem type",
            "example": "https://api.kangopenbanking.com/v1/errors/validation-error"
          },
          "title": {
            "type": "string",
            "description": "Short human-readable summary",
            "example": "Validation Error"
          },
          "status": {
            "type": "integer",
            "description": "HTTP status code",
            "example": 400
          },
          "detail": {
            "type": "string",
            "description": "Human-readable explanation specific to this occurrence",
            "example": "The amount field must be a positive integer string"
          },
          "instance": {
            "type": "string",
            "format": "uri",
            "description": "URI identifying the specific occurrence",
            "example": "https://api.kangopenbanking.com/v1/resource/3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31"
          },
          "errors": {
            "type": "array",
            "description": "Detailed field-level validation errors",
            "items": {
              "type": "object",
              "properties": {
                "field": {
                  "type": "string",
                  "example": "amount"
                },
                "message": {
                  "type": "string",
                  "example": "must match pattern ^[0-9]{1,15}$"
                },
                "code": {
                  "type": "string",
                  "example": "PATTERN_MISMATCH"
                }
              }
            }
          },
          "error_id": {
            "type": "string",
            "description": "Kang-specific trace correlation identifier. Reference this ID when contacting support. Matches the error_id field in the standard Error schema for cross-format correlation.",
            "example": "err_a1b2c3d4e5f6"
          },
          "timestamp": {
            "type": "string",
            "format": "date-time",
            "description": "UTC ISO 8601 datetime when this error occurred. Useful for correlating with server logs.",
            "example": "2025-03-27T14:32:00Z"
          }
        }
      },
      "WebhookEventPayload": {
        "type": "object",
        "description": "Base structure for all Kang webhook event payloads. The 'data' field contains the event-specific resource object.",
        "required": [
          "id",
          "event",
          "created_at",
          "api_version",
          "data"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Unique webhook delivery ID for deduplication",
            "example": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31"
          },
          "event": {
            "type": "string",
            "description": "Event type name from the subscribed events catalogue",
            "example": "charge.created",
            "enum": [
              "charge.created",
              "charge.successful",
              "charge.failed",
              "charge.pending",
              "charge.refunded",
              "charge.reversed",
              "charge.expired",
              "charge.cancelled",
              "payout.created",
              "payout.completed",
              "payout.failed",
              "payout.reversed",
              "payout.pending",
              "refund.created",
              "refund.completed",
              "refund.failed",
              "dispute.created",
              "dispute.updated",
              "dispute.won",
              "dispute.lost",
              "settlement.created",
              "settlement.paid",
              "settlement.failed",
              "subscription.created",
              "subscription.activated",
              "subscription.renewed",
              "subscription.cancelled",
              "subscription.expired",
              "subscription.payment_failed",
              "merchant.created",
              "merchant.updated",
              "merchant.verified",
              "merchant.suspended",
              "wallet.credited",
              "wallet.debited",
              "wallet.frozen",
              "escrow.created",
              "escrow.funded",
              "escrow.released",
              "escrow.disputed",
              "escrow.refunded",
              "consent.authorized",
              "consent.revoked",
              "consent.expired",
              "payment_link.created",
              "payment_link.paid",
              "payment_link.expired",
              "pay_by_bank.authorized",
              "pay_by_bank.submitted",
              "pay_by_bank.completed",
              "pay_by_bank.failed",
              "onboarding_application.approved",
              "onboarding_application.rejected",
              "merchant_kyb.verified",
              "merchant_kyb.failed",
              "credit_score.updated",
              "loan_application.approved",
              "loan_application.rejected",
              "loan_application.pending_documents"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "UTC datetime when the event was generated",
            "example": "2025-03-27T14:32:00Z"
          },
          "api_version": {
            "type": "string",
            "description": "API version that generated this event",
            "example": "4.6.0"
          },
          "livemode": {
            "type": "boolean",
            "description": "true for production events, false for sandbox/test events",
            "example": true
          },
          "data": {
            "type": "object",
            "description": "The primary event resource. Schema varies by event type.",
            "additionalProperties": true
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Merchant-provided metadata attached to the originating resource"
          }
        }
      },
      "RateLimitError": {
        "type": "object",
        "description": "Error response returned when a client exceeds their rate limit allocation (HTTP 429). Implements RFC 7807 Problem Details.",
        "required": [
          "type",
          "title",
          "status",
          "detail",
          "error_code",
          "error_id",
          "timestamp",
          "retry_after",
          "limit"
        ],
        "properties": {
          "type": {
            "type": "string",
            "format": "uri",
            "example": "https://kangopenbanking.com/errors/rate-limit-exceeded"
          },
          "title": {
            "type": "string",
            "example": "Too Many Requests"
          },
          "status": {
            "type": "integer",
            "example": 429
          },
          "detail": {
            "type": "string",
            "example": "Rate limit of 300 requests per minute exceeded for client_id tpp_abc123."
          },
          "error_code": {
            "type": "string",
            "example": "AUTH_005"
          },
          "error_id": {
            "type": "string",
            "example": "err_ratelimit_9f3a2b"
          },
          "timestamp": {
            "type": "string",
            "format": "date-time",
            "example": "2026-04-10T10:00:00Z"
          },
          "retry_after": {
            "type": "integer",
            "description": "Seconds until the rate limit window resets.",
            "example": 37
          },
          "limit": {
            "type": "integer",
            "description": "The rate limit ceiling for this endpoint.",
            "example": 300
          }
        }
      },
      "TransactionOBIE": {
        "type": "object",
        "description": "OBIE Read/Write Data API v3.1-compatible Transaction representation. Use this schema variant when consuming or producing OBIE-aligned payloads. The primary `Transaction` schema retains its snake_case fields for the canonical Kang OB representation; PascalCase aliases on Transaction are deprecated and will be removed in v5.0.0.",
        "properties": {
          "AccountId": {
            "type": "string",
            "description": "OBIE alias for the account identifier. Maps to account_id in parent resource context."
          },
          "TransactionId": {
            "type": "string",
            "description": "OBIE alias for transaction_id."
          },
          "Amount": {
            "type": "string",
            "pattern": "^[0-9]{1,15}$",
            "description": "OBIE alias for amount."
          },
          "Currency": {
            "type": "string",
            "enum": [
              "XAF",
              "XOF",
              "USD",
              "EUR",
              "GBP",
              "CNY",
              "NGN",
              "GHS",
              "KES",
              "ZAR"
            ],
            "description": "OBIE alias for currency."
          },
          "CreditDebitIndicator": {
            "type": "string",
            "enum": [
              "Credit",
              "Debit"
            ],
            "description": "OBIE alias for type. Maps credit/debit to transaction direction."
          },
          "BookingDateTime": {
            "type": "string",
            "format": "date-time",
            "description": "OBIE alias for booking_date."
          },
          "ValueDateTime": {
            "type": "string",
            "format": "date-time",
            "description": "OBIE alias for value_date."
          },
          "TransactionInformation": {
            "type": "string",
            "maxLength": 500,
            "description": "OBIE OBTransaction6 alias for the description field. Narrative text conveying information from the originator to the beneficiary about the payment transaction.",
            "example": "Payment for Invoice INV-2025-001 — Professional Services"
          },
          "Status": {
            "type": "string",
            "enum": [
              "Booked",
              "Pending",
              "Rejected"
            ],
            "description": "OBIE OBTransaction6 transaction status. Booked = settled, Pending = authorised but not yet settled, Rejected = declined or failed."
          }
        },
        "required": [
          "AccountId",
          "TransactionId",
          "Amount",
          "CreditDebitIndicator",
          "BookingDateTime",
          "Status"
        ],
        "x-obie-version": "3.1.10",
        "x-obie-spec": "https://standards.openbanking.org.uk/api-specifications/"
      },
      "WebhookEvent": {
        "type": "object",
        "required": [
          "id",
          "type",
          "created_at",
          "data"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "type": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "data": {
            "type": "object"
          }
        },
        "description": "A webhook event envelope: the event type, unique event identifier, creation timestamp and the resource payload delivered to subscribers."
      },
      "BudgetCategory": {
        "type": "object",
        "required": [
          "id",
          "name",
          "icon",
          "colour",
          "limit",
          "spent"
        ],
        "properties": {
          "id": {
            "type": "string",
            "example": "cat_food"
          },
          "name": {
            "type": "string",
            "example": "Food & Market"
          },
          "icon": {
            "type": "string",
            "example": "ShoppingCart"
          },
          "colour": {
            "type": "string",
            "pattern": "^#[0-9A-Fa-f]{6}$",
            "example": "#10D9A0"
          },
          "limit": {
            "type": "integer",
            "format": "int64",
            "minimum": 0,
            "description": "Amount in XAF (zero-decimal)."
          },
          "spent": {
            "type": "integer",
            "format": "int64",
            "minimum": 0,
            "description": "Amount in XAF (zero-decimal)."
          },
          "remaining": {
            "type": "integer",
            "format": "int64",
            "minimum": 0,
            "description": "Amount in XAF (zero-decimal)."
          },
          "percentage_used": {
            "type": "number",
            "format": "float",
            "minimum": 0
          },
          "transaction_count": {
            "type": "integer",
            "minimum": 0
          },
          "top_merchant": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "description": "A spending category used to classify transactions for budgeting and analytics."
      },
      "Budget": {
        "type": "object",
        "required": [
          "id",
          "consumer_id",
          "name",
          "period",
          "start_date",
          "end_date",
          "total_limit",
          "currency",
          "status",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "example": "bgt_01HXYZ"
          },
          "consumer_id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string",
            "example": "May 2026 Budget"
          },
          "period": {
            "type": "string",
            "enum": [
              "monthly",
              "weekly",
              "custom"
            ]
          },
          "start_date": {
            "type": "string",
            "format": "date"
          },
          "end_date": {
            "type": "string",
            "format": "date"
          },
          "total_limit": {
            "type": "integer",
            "format": "int64",
            "minimum": 0,
            "description": "Amount in XAF (zero-decimal)."
          },
          "categories": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/BudgetCategory"
            }
          },
          "currency": {
            "type": "string",
            "enum": [
              "XAF"
            ],
            "default": "XAF"
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "paused",
              "archived"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "description": "A budget for a category and period, holding the allocated amount and the spend accumulated against it."
      },
      "BudgetCreateRequest": {
        "type": "object",
        "required": [
          "name",
          "period",
          "start_date",
          "end_date",
          "total_limit"
        ],
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 80
          },
          "period": {
            "type": "string",
            "enum": [
              "monthly",
              "weekly",
              "custom"
            ]
          },
          "start_date": {
            "type": "string",
            "format": "date"
          },
          "end_date": {
            "type": "string",
            "format": "date"
          },
          "total_limit": {
            "type": "integer",
            "format": "int64",
            "minimum": 0,
            "description": "Amount in XAF (zero-decimal)."
          },
          "categories": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "id",
                "limit"
              ],
              "properties": {
                "id": {
                  "type": "string"
                },
                "limit": {
                  "type": "integer",
                  "format": "int64",
                  "minimum": 0,
                  "description": "Amount in XAF (zero-decimal)."
                }
              }
            }
          }
        },
        "description": "Request payload used to create a budget for a category and period."
      },
      "BudgetSummary": {
        "type": "object",
        "required": [
          "budget_id",
          "period_start",
          "period_end",
          "total_limit",
          "total_spent",
          "total_remaining",
          "percentage_used",
          "currency"
        ],
        "properties": {
          "budget_id": {
            "type": "string"
          },
          "period_start": {
            "type": "string",
            "format": "date"
          },
          "period_end": {
            "type": "string",
            "format": "date"
          },
          "total_limit": {
            "type": "integer",
            "format": "int64",
            "minimum": 0,
            "description": "Amount in XAF (zero-decimal)."
          },
          "total_spent": {
            "type": "integer",
            "format": "int64",
            "minimum": 0,
            "description": "Amount in XAF (zero-decimal)."
          },
          "total_remaining": {
            "type": "integer",
            "format": "int64",
            "minimum": 0,
            "description": "Amount in XAF (zero-decimal)."
          },
          "percentage_used": {
            "type": "number",
            "format": "float"
          },
          "days_remaining": {
            "type": "integer"
          },
          "projected_overspend": {
            "type": "boolean"
          },
          "projected_end_balance": {
            "type": "integer",
            "format": "int64",
            "minimum": 0,
            "description": "Amount in XAF (zero-decimal)."
          },
          "categories": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/BudgetCategory"
            }
          },
          "currency": {
            "type": "string",
            "enum": [
              "XAF"
            ]
          }
        },
        "description": "An aggregated view of a budget: allocation, spend to date, remaining amount and utilisation for the current period."
      },
      "CategoryCreateRequest": {
        "type": "object",
        "required": [
          "name",
          "icon",
          "colour",
          "limit"
        ],
        "properties": {
          "name": {
            "type": "string"
          },
          "icon": {
            "type": "string"
          },
          "colour": {
            "type": "string",
            "pattern": "^#[0-9A-Fa-f]{6}$"
          },
          "limit": {
            "type": "integer",
            "format": "int64",
            "minimum": 0,
            "description": "Amount in XAF (zero-decimal)."
          }
        },
        "description": "Request payload used to create a spending category."
      },
      "CategoryRule": {
        "type": "object",
        "required": [
          "id",
          "pattern",
          "category_id"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "pattern": {
            "type": "string",
            "description": "Substring or regex applied to transaction description."
          },
          "category_id": {
            "type": "string"
          },
          "priority": {
            "type": "integer",
            "default": 100
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "description": "An automatic categorisation rule matching transaction attributes to a spending category."
      },
      "SavingsGoal": {
        "type": "object",
        "required": [
          "id",
          "name",
          "target_amount",
          "current_amount",
          "status",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "example": "goal_01HXYZ"
          },
          "name": {
            "type": "string"
          },
          "target_amount": {
            "type": "integer",
            "format": "int64",
            "minimum": 0,
            "description": "Amount in XAF (zero-decimal)."
          },
          "current_amount": {
            "type": "integer",
            "format": "int64",
            "minimum": 0,
            "description": "Amount in XAF (zero-decimal)."
          },
          "deadline": {
            "type": "string",
            "format": "date"
          },
          "icon": {
            "type": "string"
          },
          "colour": {
            "type": "string",
            "pattern": "^#[0-9A-Fa-f]{6}$"
          },
          "round_up_enabled": {
            "type": "boolean",
            "default": false
          },
          "round_up_nearest": {
            "type": [
              "integer",
              "null"
            ],
            "enum": [
              500,
              1000,
              2000,
              null
            ]
          },
          "linked_piggy_bank_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "completed",
              "paused"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "description": "A goal-based savings target, including the target amount, deadline and optional round-up configuration."
      },
      "GoalProgress": {
        "type": "object",
        "required": [
          "goal_id",
          "percentage_complete",
          "amount_remaining"
        ],
        "properties": {
          "goal_id": {
            "type": "string"
          },
          "percentage_complete": {
            "type": "number",
            "format": "float"
          },
          "amount_remaining": {
            "type": "integer",
            "format": "int64",
            "minimum": 0,
            "description": "Amount in XAF (zero-decimal)."
          },
          "projected_completion_date": {
            "type": "string",
            "format": "date"
          },
          "weekly_required": {
            "type": "integer",
            "format": "int64",
            "minimum": 0,
            "description": "Amount in XAF (zero-decimal)."
          },
          "on_track": {
            "type": "boolean"
          },
          "milestones_reached": {
            "type": "array",
            "items": {
              "type": "integer",
              "enum": [
                25,
                50,
                75,
                100
              ]
            }
          },
          "next_milestone": {
            "type": [
              "integer",
              "null"
            ]
          },
          "round_up_total_this_month": {
            "type": "integer",
            "format": "int64",
            "minimum": 0,
            "description": "Amount in XAF (zero-decimal)."
          }
        },
        "description": "Progress against a savings goal: amount saved, amount remaining and the projected completion position."
      },
      "NjangiSchedule": {
        "type": "object",
        "required": [
          "group_id",
          "next_contribution_date",
          "next_contribution_amount"
        ],
        "properties": {
          "group_id": {
            "type": "string"
          },
          "group_name": {
            "type": "string"
          },
          "next_contribution_date": {
            "type": "string",
            "format": "date"
          },
          "next_contribution_amount": {
            "type": "integer",
            "format": "int64",
            "minimum": 0,
            "description": "Amount in XAF (zero-decimal)."
          },
          "days_until_due": {
            "type": "integer"
          },
          "budget_impact_xaf": {
            "type": "integer",
            "format": "int64",
            "minimum": 0,
            "description": "Amount in XAF (zero-decimal)."
          },
          "reminder_enabled": {
            "type": "boolean"
          }
        },
        "description": "The rotating contribution and payout schedule for a Njangi group."
      },
      "BudgetInsight": {
        "type": "object",
        "required": [
          "answer",
          "lang",
          "generated_at"
        ],
        "properties": {
          "answer": {
            "type": "string"
          },
          "lang": {
            "type": "string",
            "enum": [
              "en",
              "fr",
              "pid"
            ],
            "description": "Response language: English, French, or Cameroon Pidgin."
          },
          "confidence": {
            "type": "number",
            "format": "float",
            "minimum": 0,
            "maximum": 1
          },
          "suggested_action": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "update_category_limit",
                  "create_goal",
                  "pause_category",
                  "enable_roundup"
                ]
              },
              "category_id": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "suggested_limit": {
                "type": [
                  "integer",
                  "null"
                ]
              }
            }
          },
          "generated_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "description": "A cached AI-generated budgeting insight for the authenticated user, with the period it was derived from."
      },
      "InsightAskRequest": {
        "type": "object",
        "required": [
          "question",
          "lang"
        ],
        "properties": {
          "question": {
            "type": "string",
            "maxLength": 500
          },
          "lang": {
            "type": "string",
            "enum": [
              "en",
              "fr",
              "pid"
            ],
            "description": "Response language: English, French, or Cameroon Pidgin."
          },
          "context": {
            "type": "string",
            "enum": [
              "budget_summary",
              "category",
              "goal",
              "general"
            ]
          }
        },
        "description": "Request payload asking the budgeting adviser a free-text question. Requests are rate-limited per user per day."
      },
      "InsightAskResponse": {
        "$ref": "#/components/schemas/BudgetInsight",
        "description": "The budgeting adviser answer, together with the remaining daily question allowance."
      },
      "BudgetAlert": {
        "type": "object",
        "required": [
          "id",
          "type",
          "severity",
          "message",
          "created_at",
          "dismissed"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "type": {
            "type": "string",
            "enum": [
              "budget.threshold_reached",
              "budget.overspent",
              "goal.milestone_reached",
              "njangi.contribution_due",
              "budget.unusual_transaction"
            ]
          },
          "severity": {
            "type": "string",
            "enum": [
              "info",
              "warning",
              "critical"
            ]
          },
          "message": {
            "type": "string"
          },
          "category_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "dismissed": {
            "type": "boolean"
          }
        },
        "description": "A budget alert raised when spending crosses a configured threshold, until it is dismissed by the user."
      },
      "MonthlyAnalytics": {
        "type": "object",
        "required": [
          "months"
        ],
        "properties": {
          "months": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "month": {
                  "type": "string",
                  "example": "2026-03"
                },
                "total_spent": {
                  "type": "integer",
                  "format": "int64",
                  "minimum": 0,
                  "description": "Amount in XAF (zero-decimal)."
                },
                "by_category": {
                  "type": "object",
                  "additionalProperties": {
                    "type": "integer",
                    "format": "int64",
                    "minimum": 0,
                    "description": "Amount in XAF (zero-decimal)."
                  }
                }
              }
            }
          }
        },
        "description": "Aggregated monthly spending analytics for the authenticated user, broken down by category."
      },
      "MerchantAnalytics": {
        "type": "object",
        "required": [
          "period",
          "merchants"
        ],
        "properties": {
          "period": {
            "type": "string"
          },
          "merchants": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "name": {
                  "type": "string"
                },
                "category_id": {
                  "type": "string"
                },
                "total_spent": {
                  "type": "integer",
                  "format": "int64",
                  "minimum": 0,
                  "description": "Amount in XAF (zero-decimal)."
                },
                "transaction_count": {
                  "type": "integer"
                }
              }
            }
          }
        },
        "description": "Aggregated spending analytics grouped by merchant for the requested period."
      },
      "PaymentIntent": {
        "type": "object",
        "description": "Rail-agnostic asynchronous payment intent. Models the canonical lifecycle of any payment from creation through terminal state. State machine (Stripe API Reference §payment_intents): requires_payment_method → requires_confirmation → processing → (requires_action → processing →)* succeeded | canceled | failed.",
        "required": [
          "id",
          "amount",
          "currency",
          "status",
          "payment_method_types",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "amount": {
            "type": "string",
            "description": "Smallest currency unit; for XAF/XOF this is the whole amount (zero-decimal). Decimal string to preserve exact monetary precision.",
            "pattern": "^-?[0-9]{1,15}(\\.[0-9]{1,4})?$"
          },
          "currency": {
            "type": "string",
            "pattern": "^[A-Z]{3}$"
          },
          "status": {
            "type": "string",
            "enum": [
              "requires_payment_method",
              "requires_confirmation",
              "processing",
              "requires_action",
              "succeeded",
              "canceled",
              "failed"
            ]
          },
          "payment_method_types": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "mobile_money",
                "bank_transfer",
                "card",
                "pay_by_bank",
                "wallet"
              ]
            },
            "minItems": 1
          },
          "next_action": {
            "type": [
              "object",
              "null"
            ],
            "description": "Present when status is `requires_action`. Tells the client what to do next.",
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "redirect_to_url",
                  "display_qr",
                  "use_stk_push",
                  "poll_provider"
                ]
              },
              "redirect_to_url": {
                "type": "object",
                "properties": {
                  "url": {
                    "type": "string",
                    "format": "uri"
                  },
                  "return_url": {
                    "type": "string",
                    "format": "uri"
                  }
                }
              },
              "display_qr": {
                "type": "object",
                "properties": {
                  "qr_payload": {
                    "type": "string"
                  }
                }
              },
              "use_stk_push": {
                "type": "object",
                "properties": {
                  "msisdn": {
                    "type": "string"
                  },
                  "operator": {
                    "type": "string"
                  }
                }
              }
            }
          },
          "last_error": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "code": {
                "type": "string"
              },
              "message": {
                "type": "string"
              }
            }
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "metadata": {
            "type": "object",
            "additionalProperties": true
          },
          "customer_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "child_intent_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "ID of the underlying rail-specific intent (e.g. pay-by-bank intent or funding intent)."
          },
          "child_resource": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              null,
              "pay_by_bank_intent",
              "funding_intent",
              "gateway_charge"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "succeeded_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "canceled_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "PaymentIntentCreate": {
        "type": "object",
        "required": [
          "amount",
          "currency",
          "payment_method_types"
        ],
        "properties": {
          "amount": {
            "type": "string",
            "pattern": "^-?[0-9]{1,15}(\\.[0-9]{1,4})?$",
            "description": "Decimal string to preserve exact monetary precision."
          },
          "currency": {
            "type": "string",
            "pattern": "^[A-Z]{3}$"
          },
          "payment_method_types": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "mobile_money",
                "bank_transfer",
                "card",
                "pay_by_bank",
                "wallet"
              ]
            },
            "minItems": 1
          },
          "confirm": {
            "type": "boolean",
            "default": false,
            "description": "If true, attempt immediate confirmation. If false, intent is created in `requires_confirmation`."
          },
          "description": {
            "type": "string"
          },
          "metadata": {
            "type": "object",
            "additionalProperties": true
          },
          "customer_id": {
            "type": "string",
            "format": "uuid"
          }
        },
        "description": "Request payload used to create a payment intent."
      },
      "PaymentIntentList": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PaymentIntent"
            }
          },
          "has_more": {
            "type": "boolean"
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "description": "A paginated collection of payment intents."
      },
      "MobileMoneyErrorCode": {
        "type": "string",
        "description": "Unified KOB mobile-money error code. Maps every provider-specific code (MTN MoMo, Orange Money, Wave, M-Pesa) to a single taxonomy so SDKs can branch deterministically. See `/developer/reference/mobile-money-errors` for the full mapping.",
        "enum": [
          "insufficient_funds",
          "invalid_msisdn",
          "subscriber_not_found",
          "subscriber_pin_blocked",
          "subscriber_kyc_incomplete",
          "subscriber_limit_exceeded",
          "duplicate_transaction",
          "transaction_expired",
          "transaction_declined",
          "provider_timeout",
          "provider_unavailable",
          "currency_not_supported",
          "amount_below_minimum",
          "amount_above_maximum",
          "internal_error"
        ]
      },
      "MobileMoneyProviderError": {
        "type": "object",
        "description": "Raw upstream error preserved for audit + support. Use `normalized_code` for programmatic branching.",
        "required": [
          "provider",
          "raw_code",
          "normalized_code"
        ],
        "properties": {
          "provider": {
            "type": "string",
            "enum": [
              "mtn",
              "orange",
              "wave",
              "mpesa",
              "airtel"
            ]
          },
          "raw_code": {
            "type": "string",
            "description": "Verbatim provider error code (e.g. MTN ‘NOT_ENOUGH_FUNDS’)."
          },
          "raw_message": {
            "type": "string"
          },
          "normalized_code": {
            "$ref": "#/components/schemas/MobileMoneyErrorCode"
          },
          "retryable": {
            "type": "boolean"
          }
        }
      },
      "ConsentCreate": {
        "type": "object",
        "required": [
          "type",
          "permissions"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "AISP",
              "PISP",
              "CBPII"
            ]
          },
          "permissions": {
            "type": "array",
            "minItems": 1,
            "items": {
              "type": "string",
              "enum": [
                "ReadAccountsBasic",
                "ReadAccountsDetail",
                "ReadBalances",
                "ReadTransactionsBasic",
                "ReadTransactionsDetail",
                "ReadBeneficiariesBasic",
                "ReadStandingOrdersBasic",
                "ReadDirectDebitsBasic",
                "ReadPAN",
                "InitiatePayment"
              ]
            }
          },
          "expiration_date": {
            "type": "string",
            "format": "date-time"
          },
          "transaction_from_date": {
            "type": "string",
            "format": "date"
          },
          "transaction_to_date": {
            "type": "string",
            "format": "date"
          },
          "psu_identifier": {
            "type": "string",
            "description": "PSU MSISDN or customer reference."
          }
        },
        "description": "Request payload used to create an account-access or payment consent."
      },
      "ConsentList": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Consent"
            }
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "description": "A paginated collection of consents granted by the authenticated user."
      },
      "StatementRequest": {
        "type": "object",
        "required": [
          "account_id",
          "period_from",
          "period_to"
        ],
        "properties": {
          "account_id": {
            "type": "string",
            "format": "uuid"
          },
          "period_from": {
            "type": "string",
            "format": "date"
          },
          "period_to": {
            "type": "string",
            "format": "date"
          },
          "format": {
            "type": "string",
            "enum": [
              "camt053",
              "pdf",
              "csv"
            ],
            "default": "camt053"
          }
        },
        "description": "Request payload used to generate an account statement for a date range."
      },
      "Statement": {
        "type": "object",
        "required": [
          "statement_id",
          "account_id",
          "period_from",
          "period_to",
          "format",
          "status"
        ],
        "properties": {
          "statement_id": {
            "type": "string",
            "format": "uuid"
          },
          "account_id": {
            "type": "string",
            "format": "uuid"
          },
          "period_from": {
            "type": "string",
            "format": "date"
          },
          "period_to": {
            "type": "string",
            "format": "date"
          },
          "format": {
            "type": "string",
            "enum": [
              "camt053",
              "pdf",
              "csv"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "ready",
              "failed"
            ]
          },
          "download_url": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri"
          },
          "generated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        },
        "description": "Statement metadata: the covered period, generation status and the download reference for the produced document."
      },
      "RateLimitTier": {
        "type": "object",
        "required": [
          "tier",
          "requests_per_minute",
          "burst",
          "concurrent_connections"
        ],
        "properties": {
          "tier": {
            "type": "string",
            "enum": [
              "free",
              "pro",
              "enterprise"
            ]
          },
          "requests_per_minute": {
            "type": "integer"
          },
          "burst": {
            "type": "integer"
          },
          "concurrent_connections": {
            "type": "integer"
          },
          "webhook_deliveries_per_minute": {
            "type": "integer"
          },
          "idempotency_window_hours": {
            "type": "integer"
          }
        },
        "description": "A single rate-limit tier, defining the request allowance and window applied to callers on that tier."
      },
      "RateLimitTiers": {
        "type": "object",
        "required": [
          "data"
        ],
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RateLimitTier"
            }
          }
        },
        "description": "The published set of rate-limit tiers applied by the platform."
      },
      "ExpressUnionPickup": {
        "type": "object",
        "description": "Express Union cash-pickup envelope. Returned in next_action when channel=mobile_money and provider=ExpressUnion.",
        "properties": {
          "pickup_code": {
            "type": "string",
            "minLength": 6,
            "maxLength": 12,
            "example": "EU8K2N4"
          },
          "pickup_locations_url": {
            "type": "string",
            "format": "uri",
            "example": "https://expressunion.cm/agences"
          },
          "expires_at": {
            "type": "string",
            "format": "date-time"
          },
          "recipient_name": {
            "type": "string",
            "maxLength": 120
          }
        },
        "required": [
          "pickup_code",
          "expires_at"
        ]
      },
      "CamPostAccount": {
        "type": "object",
        "description": "CamPost (La Poste du Cameroun) postal financial account identifier.",
        "properties": {
          "postal_account": {
            "type": "string",
            "pattern": "^CP[0-9]{8,12}$",
            "example": "CP00045123987"
          },
          "branch_code": {
            "type": "string",
            "maxLength": 6,
            "example": "YDE01"
          }
        },
        "required": [
          "postal_account"
        ]
      },
      "RtpSla": {
        "type": "object",
        "description": "Real-time payment SLA hints. Indicates the expected confirmation window for the underlying rail. Targets are p50/p95 based on the trailing 30-day production sample (see /developer/reference/rtp-sla).",
        "properties": {
          "expected_completion_seconds": {
            "type": "integer",
            "minimum": 1,
            "maximum": 86400,
            "example": 18
          },
          "sla_tier": {
            "type": "string",
            "enum": [
              "instant",
              "p50_30s",
              "p95_60s",
              "p99_300s",
              "best_effort"
            ],
            "example": "p50_30s"
          },
          "retry_after_seconds": {
            "type": "integer",
            "minimum": 1,
            "maximum": 3600,
            "example": 3
          },
          "provider_p50_ms": {
            "type": "integer",
            "minimum": 0,
            "example": 18000
          },
          "provider_p95_ms": {
            "type": "integer",
            "minimum": 0,
            "example": 42000
          }
        },
        "required": [
          "expected_completion_seconds",
          "sla_tier"
        ]
      },
      "LocalizedError": {
        "type": "object",
        "description": "Localized RFC 7807 error envelope. Returned by /v1/errors/{code}.",
        "properties": {
          "code": {
            "type": "string",
            "example": "AUTH_001"
          },
          "type": {
            "type": "string",
            "format": "uri",
            "example": "https://docs.kangopenbanking.com/errors/AUTH_001"
          },
          "title_en": {
            "type": "string",
            "example": "Invalid access token"
          },
          "title_fr": {
            "type": "string",
            "example": "Jeton d'accès invalide"
          },
          "detail_en": {
            "type": "string"
          },
          "detail_fr": {
            "type": "string"
          },
          "status": {
            "type": "integer",
            "example": 401
          },
          "remediation_url": {
            "type": "string",
            "format": "uri"
          }
        },
        "required": [
          "code",
          "title_en",
          "title_fr",
          "status"
        ]
      },
      "NinVerificationRequest": {
        "type": "object",
        "properties": {
          "country": {
            "type": "string",
            "enum": [
              "CM",
              "GA",
              "CG",
              "TD",
              "CF",
              "GQ"
            ],
            "example": "CM"
          },
          "nin": {
            "type": "string",
            "pattern": "^[A-Z0-9]{8,18}$",
            "example": "11999900001234"
          },
          "holder_first_name": {
            "type": "string",
            "maxLength": 80
          },
          "holder_last_name": {
            "type": "string",
            "maxLength": 80
          },
          "holder_dob": {
            "type": "string",
            "format": "date",
            "example": "1990-05-12"
          },
          "consent_id": {
            "type": "string",
            "format": "uuid"
          }
        },
        "required": [
          "country",
          "nin",
          "consent_id"
        ],
        "description": "Request payload used to verify a National Identification Number against the issuing registry."
      },
      "NinVerificationResult": {
        "type": "object",
        "properties": {
          "match": {
            "type": "boolean",
            "example": true
          },
          "score": {
            "type": "integer",
            "minimum": 0,
            "maximum": 100,
            "example": 97
          },
          "holder_full_name": {
            "type": "string",
            "example": "MBALLA NGONO Jean"
          },
          "holder_dob": {
            "type": "string",
            "format": "date"
          },
          "issuing_authority": {
            "type": "string",
            "example": "ANTIC Cameroun"
          },
          "issued_at": {
            "type": "string",
            "format": "date"
          },
          "expires_at": {
            "type": "string",
            "format": "date"
          },
          "verified_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "match",
          "score",
          "verified_at"
        ],
        "description": "The outcome of a National Identification Number verification, including the matched identity attributes."
      },
      "CniVerificationRequest": {
        "type": "object",
        "properties": {
          "country": {
            "type": "string",
            "enum": [
              "CM",
              "GA",
              "CG",
              "TD",
              "CF",
              "GQ"
            ],
            "example": "CM"
          },
          "cni_number": {
            "type": "string",
            "pattern": "^[A-Z0-9]{6,18}$",
            "example": "110123456"
          },
          "holder_first_name": {
            "type": "string",
            "maxLength": 80
          },
          "holder_last_name": {
            "type": "string",
            "maxLength": 80
          },
          "holder_dob": {
            "type": "string",
            "format": "date"
          },
          "consent_id": {
            "type": "string",
            "format": "uuid"
          }
        },
        "required": [
          "country",
          "cni_number",
          "consent_id"
        ],
        "description": "Request payload used to verify a Carte Nationale d’Identité against the issuing registry."
      },
      "CniVerificationResult": {
        "type": "object",
        "properties": {
          "match": {
            "type": "boolean",
            "example": true
          },
          "score": {
            "type": "integer",
            "minimum": 0,
            "maximum": 100,
            "example": 97
          },
          "holder_full_name": {
            "type": "string",
            "example": "MBALLA NGONO Jean"
          },
          "holder_dob": {
            "type": "string",
            "format": "date"
          },
          "issuing_authority": {
            "type": "string",
            "example": "ANTIC Cameroun"
          },
          "issued_at": {
            "type": "string",
            "format": "date"
          },
          "expires_at": {
            "type": "string",
            "format": "date"
          },
          "verified_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "match",
          "score",
          "verified_at"
        ],
        "description": "The outcome of a Carte Nationale d’Identité verification, including the matched identity attributes."
      },
      "Agent": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "agent_code": {
            "type": "string",
            "example": "AG3K7M2P"
          },
          "business_name": {
            "type": "string",
            "example": "Mama Africa Mobile Money"
          },
          "legal_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "msisdn": {
            "type": "string",
            "pattern": "^\\+?[0-9]{8,15}$",
            "example": "+237671234567"
          },
          "email": {
            "type": [
              "string",
              "null"
            ],
            "format": "email"
          },
          "country_code": {
            "type": "string",
            "enum": [
              "CM",
              "GA",
              "CG",
              "TD",
              "CF",
              "GQ"
            ],
            "example": "CM"
          },
          "region": {
            "type": [
              "string",
              "null"
            ],
            "example": "Centre"
          },
          "city": {
            "type": [
              "string",
              "null"
            ],
            "example": "Yaoundé"
          },
          "address": {
            "type": [
              "string",
              "null"
            ]
          },
          "latitude": {
            "type": [
              "number",
              "null"
            ],
            "format": "double",
            "example": 3.848
          },
          "longitude": {
            "type": [
              "number",
              "null"
            ],
            "format": "double",
            "example": 11.502
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "active",
              "suspended",
              "terminated"
            ]
          },
          "tier": {
            "type": "string",
            "enum": [
              "standard",
              "premium",
              "master"
            ]
          },
          "commission_rate": {
            "type": "number",
            "format": "double",
            "example": 0.01
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "agent_code",
          "business_name",
          "msisdn",
          "country_code",
          "status",
          "tier"
        ],
        "description": "A cash-in/cash-out agent, including location, region and operating status."
      },
      "AgentRegisterRequest": {
        "type": "object",
        "properties": {
          "business_name": {
            "type": "string",
            "minLength": 2,
            "maxLength": 200
          },
          "legal_name": {
            "type": "string",
            "maxLength": 200
          },
          "msisdn": {
            "type": "string",
            "pattern": "^\\+?[0-9]{8,15}$"
          },
          "email": {
            "type": "string",
            "format": "email"
          },
          "country_code": {
            "type": "string",
            "enum": [
              "CM",
              "GA",
              "CG",
              "TD",
              "CF",
              "GQ"
            ]
          },
          "region": {
            "type": "string"
          },
          "city": {
            "type": "string"
          },
          "address": {
            "type": "string"
          },
          "latitude": {
            "type": "number"
          },
          "longitude": {
            "type": "number"
          },
          "tier": {
            "type": "string",
            "enum": [
              "standard",
              "premium",
              "master"
            ]
          }
        },
        "required": [
          "business_name",
          "msisdn"
        ],
        "description": "Request payload used to register a new cash agent."
      },
      "AgentFloat": {
        "type": "object",
        "properties": {
          "currency": {
            "type": "string",
            "enum": [
              "XAF",
              "XOF",
              "EUR",
              "USD"
            ]
          },
          "float_balance": {
            "type": "number",
            "format": "double",
            "example": 250000,
            "deprecated": true,
            "x-successor": "float_balance_money",
            "x-sunset": "5.0.0",
            "description": "Deprecated: floating-point monetary value (IEEE-754 binary64 cannot represent decimal minor units exactly). Use `float_balance_money` instead. Removal is scheduled for v5.0.0."
          },
          "cash_balance": {
            "type": "number",
            "format": "double",
            "example": 75000,
            "deprecated": true,
            "x-successor": "cash_balance_money",
            "x-sunset": "5.0.0",
            "description": "Deprecated: floating-point monetary value (IEEE-754 binary64 cannot represent decimal minor units exactly). Use `cash_balance_money` instead. Removal is scheduled for v5.0.0."
          },
          "low_threshold": {
            "type": "number",
            "format": "double",
            "example": 50000
          },
          "last_topup_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "float_balance_money": {
            "$ref": "#/components/schemas/Money",
            "description": "Canonical string-encoded successor to `float_balance`. Amount and ISO 4217 currency travel together (ISO 20022 ActiveCurrencyAndAmount). Prefer this field: it is exact for zero-decimal currencies (XAF, XOF) and immune to IEEE-754 drift.",
            "x-added-in": "4.54.0"
          },
          "cash_balance_money": {
            "$ref": "#/components/schemas/Money",
            "description": "Canonical string-encoded successor to `cash_balance`. Amount and ISO 4217 currency travel together (ISO 20022 ActiveCurrencyAndAmount). Prefer this field: it is exact for zero-decimal currencies (XAF, XOF) and immune to IEEE-754 drift.",
            "x-added-in": "4.54.0"
          }
        },
        "required": [
          "currency",
          "float_balance",
          "cash_balance"
        ],
        "description": "The float balances an agent holds for cash operations, by currency."
      },
      "AgentFloatMutationRequest": {
        "type": "object",
        "properties": {
          "amount": {
            "type": "number",
            "format": "double",
            "minimum": 1,
            "deprecated": true,
            "x-successor": "amount_money",
            "x-sunset": "5.0.0",
            "description": "Deprecated: floating-point monetary value (IEEE-754 binary64 cannot represent decimal minor units exactly). Use `amount_money` instead. Removal is scheduled for v5.0.0."
          },
          "currency": {
            "type": "string",
            "enum": [
              "XAF",
              "XOF",
              "EUR",
              "USD"
            ],
            "default": "XAF"
          },
          "amount_money": {
            "$ref": "#/components/schemas/Money",
            "description": "Canonical string-encoded successor to `amount`. Amount and ISO 4217 currency travel together (ISO 20022 ActiveCurrencyAndAmount). Prefer this field: it is exact for zero-decimal currencies (XAF, XOF) and immune to IEEE-754 drift.",
            "x-added-in": "4.54.0"
          }
        },
        "required": [
          "amount"
        ],
        "description": "Request payload used to top up or withdraw agent float."
      },
      "AgentCashTransaction": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "agent_id": {
            "type": "string",
            "format": "uuid"
          },
          "customer_msisdn": {
            "type": [
              "string",
              "null"
            ]
          },
          "customer_user_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "tx_type": {
            "type": "string",
            "enum": [
              "cash_in",
              "cash_out",
              "float_topup",
              "float_withdraw",
              "commission"
            ]
          },
          "amount": {
            "type": "number",
            "format": "double",
            "deprecated": true,
            "x-successor": "amount_money",
            "x-sunset": "5.0.0",
            "description": "Deprecated: floating-point monetary value (IEEE-754 binary64 cannot represent decimal minor units exactly). Use `amount_money` instead. Removal is scheduled for v5.0.0."
          },
          "currency": {
            "type": "string"
          },
          "commission_amount": {
            "type": "number",
            "format": "double",
            "deprecated": true,
            "x-successor": "commission_amount_money",
            "x-sunset": "5.0.0",
            "description": "Deprecated: floating-point monetary value (IEEE-754 binary64 cannot represent decimal minor units exactly). Use `commission_amount_money` instead. Removal is scheduled for v5.0.0."
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "completed",
              "failed",
              "reversed"
            ]
          },
          "idempotency_key": {
            "type": "string",
            "format": "uuid"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "completed_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "amount_money": {
            "$ref": "#/components/schemas/Money",
            "description": "Canonical string-encoded successor to `amount`. Amount and ISO 4217 currency travel together (ISO 20022 ActiveCurrencyAndAmount). Prefer this field: it is exact for zero-decimal currencies (XAF, XOF) and immune to IEEE-754 drift.",
            "x-added-in": "4.54.0"
          },
          "commission_amount_money": {
            "$ref": "#/components/schemas/Money",
            "description": "Canonical string-encoded successor to `commission_amount`. Amount and ISO 4217 currency travel together (ISO 20022 ActiveCurrencyAndAmount). Prefer this field: it is exact for zero-decimal currencies (XAF, XOF) and immune to IEEE-754 drift.",
            "x-added-in": "4.54.0"
          }
        },
        "required": [
          "id",
          "agent_id",
          "tx_type",
          "amount",
          "currency",
          "status",
          "idempotency_key"
        ],
        "description": "A cash-in or cash-out transaction performed at an agent, with amount, customer reference and status."
      },
      "AgentCashRequest": {
        "type": "object",
        "properties": {
          "amount": {
            "type": "number",
            "format": "double",
            "minimum": 1,
            "deprecated": true,
            "x-successor": "amount_money",
            "x-sunset": "5.0.0",
            "description": "Deprecated: floating-point monetary value (IEEE-754 binary64 cannot represent decimal minor units exactly). Use `amount_money` instead. Removal is scheduled for v5.0.0."
          },
          "currency": {
            "type": "string",
            "enum": [
              "XAF",
              "XOF"
            ],
            "default": "XAF"
          },
          "customer_msisdn": {
            "type": "string",
            "pattern": "^\\+?[0-9]{8,15}$"
          },
          "customer_user_id": {
            "type": "string",
            "format": "uuid"
          },
          "reference": {
            "type": "string",
            "maxLength": 64
          },
          "amount_money": {
            "$ref": "#/components/schemas/Money",
            "description": "Canonical string-encoded successor to `amount`. Amount and ISO 4217 currency travel together (ISO 20022 ActiveCurrencyAndAmount). Prefer this field: it is exact for zero-decimal currencies (XAF, XOF) and immune to IEEE-754 drift.",
            "x-added-in": "4.54.0"
          }
        },
        "required": [
          "amount"
        ],
        "description": "Request payload used to record a customer cash-in or cash-out at an agent."
      },
      "AdminTestWebhookRequest": {
        "type": "object",
        "required": [
          "endpoint_id",
          "event_type"
        ],
        "properties": {
          "endpoint_id": {
            "type": "string",
            "format": "uuid"
          },
          "event_type": {
            "type": "string",
            "enum": [
              "payment.succeeded",
              "payment.failed",
              "qr.paid",
              "remittance.cemac.paid",
              "agent.cashin.completed",
              "ussd.session.ended",
              "transfer.completed"
            ]
          },
          "payload": {
            "type": "object",
            "additionalProperties": true
          }
        },
        "description": "Request payload used by an administrator to dispatch a test webhook delivery to a registered endpoint."
      },
      "AdminTestWebhookResult": {
        "type": "object",
        "required": [
          "delivery_id",
          "status"
        ],
        "properties": {
          "delivery_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "event_id": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "delivered",
              "failed"
            ]
          },
          "http_status": {
            "type": "integer"
          },
          "latency_ms": {
            "type": "integer"
          },
          "signature_header": {
            "type": "string"
          },
          "endpoint_url": {
            "type": "string",
            "format": "uri"
          }
        },
        "description": "The outcome of a test webhook delivery, including the endpoint response status."
      },
      "AdminApiKey": {
        "type": "object",
        "required": [
          "id",
          "status",
          "environment"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "key_prefix": {
            "type": "string",
            "example": "sk_live_a1b2"
          },
          "label": {
            "type": "string"
          },
          "environment": {
            "type": "string",
            "enum": [
              "sandbox",
              "production"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "suspended",
              "revoked"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "suspended_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "suspended_reason": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "description": "An API key record as seen by administrators: its identifier, scopes, tier and lifecycle status. The plaintext secret is never returned."
      },
      "AdminApiKeyCreateRequest": {
        "type": "object",
        "required": [
          "merchant_id"
        ],
        "properties": {
          "merchant_id": {
            "type": "string",
            "format": "uuid"
          },
          "label": {
            "type": "string",
            "maxLength": 120
          },
          "environment": {
            "type": "string",
            "enum": [
              "sandbox",
              "production"
            ],
            "default": "sandbox"
          }
        },
        "description": "Request payload used by an administrator to issue an API key."
      },
      "AdminApiKeyCreateResponse": {
        "allOf": [
          {
            "$ref": "#/components/schemas/AdminApiKey"
          },
          {
            "type": "object",
            "required": [
              "api_key",
              "shown_once"
            ],
            "properties": {
              "api_key": {
                "type": "string",
                "example": "sk_live_…"
              },
              "shown_once": {
                "type": "boolean"
              },
              "message": {
                "type": "string"
              }
            }
          }
        ],
        "description": "The result of issuing an API key. The plaintext secret is returned exactly once and is never retrievable again."
      },
      "AdminApiKeySuspendRequest": {
        "type": "object",
        "required": [
          "action"
        ],
        "properties": {
          "action": {
            "type": "string",
            "enum": [
              "suspend",
              "resume"
            ]
          },
          "reason": {
            "type": "string",
            "maxLength": 500
          }
        },
        "description": "Request payload used by an administrator to suspend or resume an API key."
      },
      "UssdSession": {
        "type": "object",
        "required": [
          "id",
          "msisdn",
          "session_id",
          "state",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "session_id": {
            "type": "string",
            "example": "USSD-3f9d2c"
          },
          "msisdn": {
            "type": "string",
            "pattern": "^\\+?[0-9]{8,15}$",
            "example": "+237671234567"
          },
          "service_code": {
            "type": "string",
            "example": "*144#"
          },
          "state": {
            "type": "string",
            "enum": [
              "active",
              "ended",
              "expired"
            ]
          },
          "menu": {
            "type": "string",
            "example": "1. Send Money\n2. Buy Airtime\n3. Balance"
          },
          "input": {
            "type": [
              "string",
              "null"
            ]
          },
          "language": {
            "type": "string",
            "enum": [
              "en",
              "fr"
            ],
            "example": "fr"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "ended_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        },
        "description": "A USSD session: the current menu state and the text rendered back to the subscriber handset."
      },
      "UssdSessionRequest": {
        "type": "object",
        "required": [
          "session_id",
          "msisdn",
          "service_code"
        ],
        "properties": {
          "session_id": {
            "type": "string"
          },
          "msisdn": {
            "type": "string",
            "pattern": "^\\+?[0-9]{8,15}$"
          },
          "service_code": {
            "type": "string"
          },
          "input": {
            "type": [
              "string",
              "null"
            ]
          },
          "language": {
            "type": "string",
            "enum": [
              "en",
              "fr"
            ],
            "default": "fr"
          }
        },
        "description": "Request payload used to open or advance a USSD session from an aggregator."
      },
      "QrCode": {
        "type": "object",
        "required": [
          "id",
          "payload",
          "amount",
          "currency",
          "merchant_id",
          "status",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "payload": {
            "type": "string",
            "description": "EMVCo-compliant TLV payload (base64)."
          },
          "amount": {
            "type": "string",
            "pattern": "^[0-9]{1,15}$",
            "example": "5000"
          },
          "currency": {
            "type": "string",
            "enum": [
              "XAF",
              "XOF"
            ],
            "example": "XAF"
          },
          "merchant_id": {
            "type": "string",
            "format": "uuid"
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "consumed",
              "expired",
              "revoked"
            ]
          },
          "expires_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "description": "A merchant QR code payload, including the encoded payment reference and its rendering data."
      },
      "OfflineToken": {
        "type": "object",
        "required": [
          "token_id",
          "payer_id",
          "amount",
          "currency",
          "issued_at",
          "expires_at",
          "signature"
        ],
        "properties": {
          "token_id": {
            "type": "string",
            "format": "uuid"
          },
          "payer_id": {
            "type": "string",
            "format": "uuid"
          },
          "payee_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "amount": {
            "type": "string",
            "pattern": "^[0-9]{1,15}$"
          },
          "currency": {
            "type": "string",
            "enum": [
              "XAF",
              "XOF"
            ]
          },
          "issued_at": {
            "type": "string",
            "format": "date-time"
          },
          "expires_at": {
            "type": "string",
            "format": "date-time"
          },
          "signature": {
            "type": "string",
            "description": "Ed25519 detached signature (base64url)."
          },
          "redeemed_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        },
        "description": "A signed offline payment token that can be redeemed later when connectivity is restored."
      },
      "OfflineTokenIssueRequest": {
        "type": "object",
        "required": [
          "payer_id",
          "amount",
          "currency"
        ],
        "properties": {
          "payer_id": {
            "type": "string",
            "format": "uuid"
          },
          "payee_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "amount": {
            "type": "string",
            "pattern": "^[0-9]{1,15}$"
          },
          "currency": {
            "type": "string",
            "enum": [
              "XAF",
              "XOF"
            ]
          },
          "ttl_seconds": {
            "type": "integer",
            "minimum": 60,
            "maximum": 86400,
            "default": 3600
          }
        },
        "description": "Request payload used to issue a signed offline payment token."
      },
      "OfflineTokenRedeemRequest": {
        "type": "object",
        "required": [
          "token_id",
          "signature"
        ],
        "properties": {
          "token_id": {
            "type": "string",
            "format": "uuid"
          },
          "signature": {
            "type": "string"
          },
          "payee_id": {
            "type": "string",
            "format": "uuid"
          }
        },
        "description": "Request payload used to redeem a previously issued offline payment token."
      },
      "CemacCorridor": {
        "type": "object",
        "required": [
          "origin_country",
          "destination_country",
          "fee_bps",
          "fx_rate",
          "status"
        ],
        "properties": {
          "origin_country": {
            "type": "string",
            "enum": [
              "CM",
              "GA",
              "CG",
              "TD",
              "CF",
              "GQ"
            ]
          },
          "destination_country": {
            "type": "string",
            "enum": [
              "CM",
              "GA",
              "CG",
              "TD",
              "CF",
              "GQ"
            ]
          },
          "fee_bps": {
            "type": "integer",
            "minimum": 0,
            "maximum": 1000,
            "example": 100
          },
          "fx_rate": {
            "type": "number",
            "format": "double",
            "example": 1
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "suspended"
            ]
          }
        },
        "description": "An active CEMAC remittance corridor, defining the supported send and receive countries and currencies."
      },
      "CemacRemittanceQuoteRequest": {
        "type": "object",
        "required": [
          "origin_country",
          "destination_country",
          "amount"
        ],
        "properties": {
          "origin_country": {
            "type": "string",
            "enum": [
              "CM",
              "GA",
              "CG",
              "TD",
              "CF",
              "GQ"
            ]
          },
          "destination_country": {
            "type": "string",
            "enum": [
              "CM",
              "GA",
              "CG",
              "TD",
              "CF",
              "GQ"
            ]
          },
          "amount": {
            "type": "string",
            "pattern": "^[0-9]{1,15}$",
            "example": "50000"
          }
        },
        "description": "Request payload used to quote a CEMAC remittance."
      },
      "CemacRemittanceQuote": {
        "type": "object",
        "required": [
          "amount",
          "fee",
          "net",
          "receive_amount",
          "fx_rate",
          "currency"
        ],
        "properties": {
          "amount": {
            "type": "string",
            "pattern": "^[0-9]{1,15}$"
          },
          "fee": {
            "type": "string",
            "pattern": "^[0-9]{1,15}$"
          },
          "net": {
            "type": "string",
            "pattern": "^[0-9]{1,15}$"
          },
          "receive_amount": {
            "type": "string",
            "pattern": "^[0-9]{1,15}$"
          },
          "fx_rate": {
            "type": "number",
            "format": "double"
          },
          "currency": {
            "type": "string",
            "enum": [
              "XAF"
            ]
          },
          "quote_id": {
            "type": "string",
            "format": "uuid"
          },
          "expires_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "description": "A CEMAC remittance quote, including the exchange rate, fees, receive amount and quote expiry."
      },
      "CemacRemittanceTransferRequest": {
        "type": "object",
        "required": [
          "quote_id",
          "sender",
          "recipient"
        ],
        "properties": {
          "quote_id": {
            "type": "string",
            "format": "uuid"
          },
          "sender": {
            "type": "object",
            "required": [
              "full_name",
              "msisdn",
              "country"
            ],
            "properties": {
              "full_name": {
                "type": "string"
              },
              "msisdn": {
                "type": "string",
                "pattern": "^\\+?[0-9]{8,15}$"
              },
              "country": {
                "type": "string",
                "enum": [
                  "CM",
                  "GA",
                  "CG",
                  "TD",
                  "CF",
                  "GQ"
                ]
              }
            }
          },
          "recipient": {
            "type": "object",
            "required": [
              "full_name",
              "msisdn",
              "country"
            ],
            "properties": {
              "full_name": {
                "type": "string"
              },
              "msisdn": {
                "type": "string",
                "pattern": "^\\+?[0-9]{8,15}$"
              },
              "country": {
                "type": "string",
                "enum": [
                  "CM",
                  "GA",
                  "CG",
                  "TD",
                  "CF",
                  "GQ"
                ]
              }
            }
          },
          "reference": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 140
          }
        },
        "description": "Request payload used to create a CEMAC remittance transfer from an accepted quote."
      },
      "CemacRemittanceTransfer": {
        "type": "object",
        "required": [
          "id",
          "status",
          "amount",
          "fee",
          "net",
          "origin_country",
          "destination_country",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "funded",
              "settled",
              "cancelled",
              "failed"
            ]
          },
          "amount": {
            "type": "string",
            "pattern": "^[0-9]{1,15}$"
          },
          "fee": {
            "type": "string",
            "pattern": "^[0-9]{1,15}$"
          },
          "net": {
            "type": "string",
            "pattern": "^[0-9]{1,15}$"
          },
          "origin_country": {
            "type": "string",
            "enum": [
              "CM",
              "GA",
              "CG",
              "TD",
              "CF",
              "GQ"
            ]
          },
          "destination_country": {
            "type": "string",
            "enum": [
              "CM",
              "GA",
              "CG",
              "TD",
              "CF",
              "GQ"
            ]
          },
          "reference": {
            "type": [
              "string",
              "null"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "settled_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        },
        "description": "A CEMAC remittance transfer, tracking sender, beneficiary, amounts and payout status."
      },
      "NiumGlobalAccount": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "currency": {
            "type": "string",
            "enum": [
              "USD",
              "EUR",
              "GBP"
            ]
          },
          "iban": {
            "type": [
              "string",
              "null"
            ]
          },
          "account_number": {
            "type": [
              "string",
              "null"
            ]
          },
          "routing_code": {
            "type": [
              "string",
              "null"
            ]
          },
          "bic": {
            "type": [
              "string",
              "null"
            ]
          },
          "bank_name": {
            "type": "string"
          },
          "bank_address": {
            "type": [
              "string",
              "null"
            ]
          },
          "beneficiary_name": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "suspended",
              "closed"
            ]
          },
          "payout_preference_override": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "KANG_WALLET",
              "MOBILE_MONEY",
              null
            ]
          },
          "payout_channel_override": {
            "type": [
              "string",
              "null"
            ]
          },
          "mode": {
            "type": "string",
            "enum": [
              "stub",
              "sandbox",
              "live"
            ]
          }
        },
        "example": {
          "id": "f1d6f4a0-1d4e-4a3a-9e0a-1a2b3c4d5e6f",
          "currency": "USD",
          "iban": null,
          "account_number": "912345678",
          "routing_code": "021000021",
          "bic": "CHASUS33",
          "bank_name": "JPMorgan Chase (via Nium)",
          "bank_address": "383 Madison Ave, New York, NY 10179",
          "beneficiary_name": "Jane Influencer",
          "status": "active",
          "payout_preference_override": null,
          "payout_channel_override": null,
          "mode": "stub"
        },
        "description": "A global virtual account issued to a user for receiving international payments in a supported currency.",
        "required": [
          "currency",
          "status"
        ]
      },
      "NiumIncomingPayment": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "source_amount": {
            "type": "number",
            "deprecated": true,
            "x-successor": "source_amount_money",
            "x-sunset": "5.0.0",
            "description": "Deprecated: floating-point monetary value (IEEE-754 binary64 cannot represent decimal minor units exactly). Use `source_amount_money` instead. Removal is scheduled for v5.0.0."
          },
          "source_currency": {
            "type": "string"
          },
          "fx_rate_nium": {
            "type": "number"
          },
          "fx_spread_bps": {
            "type": "integer"
          },
          "xaf_gross": {
            "type": "number",
            "deprecated": true,
            "x-successor": "xaf_gross_money",
            "x-sunset": "5.0.0",
            "description": "Deprecated: floating-point monetary value (IEEE-754 binary64 cannot represent decimal minor units exactly). Use `xaf_gross_money` instead. Removal is scheduled for v5.0.0."
          },
          "xaf_spread_revenue": {
            "type": "number"
          },
          "xaf_withdrawal_fee": {
            "type": "number",
            "deprecated": true,
            "x-successor": "xaf_withdrawal_fee_money",
            "x-sunset": "5.0.0",
            "description": "Deprecated: floating-point monetary value (IEEE-754 binary64 cannot represent decimal minor units exactly). Use `xaf_withdrawal_fee_money` instead. Removal is scheduled for v5.0.0."
          },
          "xaf_net_credited": {
            "type": "number",
            "deprecated": true,
            "x-successor": "xaf_net_credited_money",
            "x-sunset": "5.0.0",
            "description": "Deprecated: floating-point monetary value (IEEE-754 binary64 cannot represent decimal minor units exactly). Use `xaf_net_credited_money` instead. Removal is scheduled for v5.0.0."
          },
          "routing": {
            "type": "string",
            "enum": [
              "KANG_WALLET",
              "MOBILE_MONEY"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "received",
              "credited",
              "payout_pending",
              "payout_completed",
              "payout_failed",
              "failed"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "source_amount_money": {
            "$ref": "#/components/schemas/Money",
            "description": "Canonical string-encoded successor to `source_amount`. Amount and ISO 4217 currency travel together (ISO 20022 ActiveCurrencyAndAmount). Prefer this field: it is exact for zero-decimal currencies (XAF, XOF) and immune to IEEE-754 drift.",
            "x-added-in": "4.54.0"
          },
          "xaf_gross_money": {
            "$ref": "#/components/schemas/Money",
            "description": "Canonical string-encoded successor to `xaf_gross`. Amount and ISO 4217 currency travel together (ISO 20022 ActiveCurrencyAndAmount). Prefer this field: it is exact for zero-decimal currencies (XAF, XOF) and immune to IEEE-754 drift.",
            "x-added-in": "4.54.0"
          },
          "xaf_withdrawal_fee_money": {
            "$ref": "#/components/schemas/Money",
            "description": "Canonical string-encoded successor to `xaf_withdrawal_fee`. Amount and ISO 4217 currency travel together (ISO 20022 ActiveCurrencyAndAmount). Prefer this field: it is exact for zero-decimal currencies (XAF, XOF) and immune to IEEE-754 drift.",
            "x-added-in": "4.54.0"
          },
          "xaf_net_credited_money": {
            "$ref": "#/components/schemas/Money",
            "description": "Canonical string-encoded successor to `xaf_net_credited`. Amount and ISO 4217 currency travel together (ISO 20022 ActiveCurrencyAndAmount). Prefer this field: it is exact for zero-decimal currencies (XAF, XOF) and immune to IEEE-754 drift.",
            "x-added-in": "4.54.0"
          }
        },
        "example": {
          "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
          "source_amount": 1,
          "source_currency": "XAF"
        },
        "description": "An incoming payment credited to a global virtual account, with sender reference and value date.",
        "required": [
          "id"
        ]
      },
      "NiumPayoutPreference": {
        "type": "object",
        "properties": {
          "payout_preference": {
            "type": "string",
            "enum": [
              "KANG_WALLET",
              "MOBILE_MONEY"
            ]
          },
          "payout_channel": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "example": {
          "payout_preference": "MOBILE_MONEY",
          "payout_channel": "237677123456"
        },
        "description": "The cash-out routing preference applied to global-account funds, either as a user default or a per-account override.",
        "required": [
          "payout_preference"
        ]
      },
      "NiumWebhookEvent": {
        "type": "object",
        "required": [
          "eventType",
          "transactionId",
          "accountId",
          "amount",
          "currency"
        ],
        "properties": {
          "eventType": {
            "type": "string",
            "example": "payment_incoming"
          },
          "transactionId": {
            "type": "string"
          },
          "accountId": {
            "type": "string"
          },
          "amount": {
            "type": "number",
            "deprecated": true,
            "x-successor": "amount_money",
            "x-sunset": "5.0.0",
            "description": "Deprecated: floating-point monetary value (IEEE-754 binary64 cannot represent decimal minor units exactly). Use `amount_money` instead. Removal is scheduled for v5.0.0."
          },
          "currency": {
            "type": "string",
            "enum": [
              "USD",
              "EUR",
              "GBP"
            ]
          },
          "senderName": {
            "type": "string"
          },
          "reference": {
            "type": "string"
          },
          "amount_money": {
            "$ref": "#/components/schemas/Money",
            "description": "Canonical string-encoded successor to `amount`. Amount and ISO 4217 currency travel together (ISO 20022 ActiveCurrencyAndAmount). Prefer this field: it is exact for zero-decimal currencies (XAF, XOF) and immune to IEEE-754 drift.",
            "x-added-in": "4.54.0"
          }
        },
        "example": {
          "eventType": "payment_incoming",
          "transactionId": "NIUM_TX_001",
          "accountId": "nium_acc_abc123",
          "amount": 250,
          "currency": "USD",
          "senderName": "YouTube Adsense",
          "reference": "Creator payout March 2026"
        },
        "description": "A provider webhook event for global accounts. Inbound provider events are authoritative for account and payment state."
      },
      "Money": {
        "type": "object",
        "description": "Canonical monetary value. String-encoded minor units to avoid floating-point drift. Currency is an ISO 4217 code (or XAF/XOF for CEMAC/UEMOA zero-decimal).",
        "required": [
          "amount",
          "currency"
        ],
        "properties": {
          "amount": {
            "type": "string",
            "pattern": "^-?[0-9]{1,20}(\\.[0-9]{1,8})?$",
            "description": "Decimal string. For zero-decimal currencies (XAF, XOF, JPY) send integer strings only.",
            "example": "15000"
          },
          "currency": {
            "type": "string",
            "pattern": "^[A-Z]{3}$",
            "description": "ISO 4217 currency code (uppercase).",
            "example": "XAF"
          }
        },
        "x-added-in": "4.54.0",
        "x-status": "stable"
      },
      "AgentTransactionResponse": {
        "type": "object",
        "required": [
          "transaction_id",
          "agent_id",
          "type",
          "amount",
          "currency",
          "status",
          "balance_after",
          "created_at"
        ],
        "properties": {
          "transaction_id": {
            "type": "string",
            "format": "uuid",
            "description": "Unique ledger transaction identifier."
          },
          "agent_id": {
            "type": "string",
            "format": "uuid"
          },
          "type": {
            "type": "string",
            "enum": [
              "float_topup",
              "float_withdraw",
              "cash_in",
              "cash_out"
            ]
          },
          "amount": {
            "type": "string",
            "pattern": "^[0-9]{1,15}$",
            "description": "Amount in minor units (XAF/XOF are zero-decimal — value equals major units)."
          },
          "currency": {
            "type": "string",
            "enum": [
              "XAF",
              "XOF"
            ],
            "description": "ISO 4217 currency."
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "completed",
              "failed",
              "reversed"
            ]
          },
          "balance_after": {
            "type": "string",
            "pattern": "^[0-9]{1,15}$",
            "description": "Agent float balance after this transaction, in minor units."
          },
          "reference": {
            "type": [
              "string",
              "null"
            ],
            "description": "Optional external reference supplied by the caller."
          },
          "customer_phone": {
            "type": [
              "string",
              "null"
            ],
            "description": "Present on cash-in / cash-out operations."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "description": "Result of an agent float or cash movement. Zero-decimal currency amounts follow the KOB minor-unit string convention."
      },
      "JournalLine": {
        "type": "object",
        "description": "A single side of a double-entry journal entry. Exactly one of `debit` or `credit` must be non-zero.",
        "properties": {
          "ledger_account_id": {
            "type": "string",
            "format": "uuid",
            "description": "Ledger account this line posts against."
          },
          "debit": {
            "type": "number",
            "minimum": 0,
            "default": 0,
            "description": "Debit amount. Minor-unit-safe decimal amount. Zero-decimal currencies (XAF, XOF) MUST be supplied as whole numbers.",
            "example": 1000000
          },
          "credit": {
            "type": "number",
            "minimum": 0,
            "default": 0,
            "description": "Credit amount. Minor-unit-safe decimal amount. Zero-decimal currencies (XAF, XOF) MUST be supplied as whole numbers.",
            "example": 0
          },
          "memo": {
            "type": "string",
            "maxLength": 255,
            "description": "Optional line-level narrative.",
            "example": "Loan principal"
          }
        },
        "required": [
          "ledger_account_id",
          "debit",
          "credit"
        ],
        "additionalProperties": false
      },
      "JournalEntryCreateRequest": {
        "type": "object",
        "description": "Client-supplied journal entry. Server-generated fields (`id`, `created_at`) are not accepted. The entry MUST balance: the sum of `lines[].debit` MUST equal the sum of `lines[].credit`. Unbalanced entries are rejected with 422 `journal_entry_unbalanced`.",
        "properties": {
          "entry_date": {
            "type": "string",
            "format": "date",
            "description": "Accounting date of the entry.",
            "example": "2026-05-02"
          },
          "description": {
            "type": "string",
            "minLength": 1,
            "maxLength": 500,
            "example": "Loan disbursement - APP-2026-001"
          },
          "reference_type": {
            "type": "string",
            "enum": [
              "payment",
              "loan",
              "savings",
              "fee",
              "interest",
              "manual"
            ],
            "example": "loan"
          },
          "reference_id": {
            "type": "string",
            "format": "uuid",
            "description": "Identifier of the originating business object. Required for every non-manual reference type.",
            "example": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31"
          },
          "lines": {
            "type": "array",
            "minItems": 2,
            "maxItems": 200,
            "description": "Balanced set of journal lines. At least one debit line and one credit line are required.",
            "items": {
              "$ref": "#/components/schemas/JournalLine"
            }
          }
        },
        "required": [
          "entry_date",
          "description",
          "reference_type",
          "lines"
        ],
        "additionalProperties": false
      },
      "GenericSuccessResponse": {
        "type": "object",
        "description": "Generic successful operation envelope.",
        "required": [
          "success"
        ],
        "properties": {
          "success": {
            "type": "boolean",
            "description": "True when the operation completed successfully."
          },
          "data": {
            "type": "object",
            "additionalProperties": true,
            "description": "Operation-specific payload."
          },
          "request_id": {
            "type": "string",
            "description": "Correlation identifier for this request."
          }
        }
      }
    },
    "parameters": {
      "IdempotencyKey": {
        "name": "Idempotency-Key",
        "in": "header",
        "required": true,
        "schema": {
          "type": "string",
          "format": "uuid",
          "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$",
          "maxLength": 255
        },
        "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
      },
      "Limit": {
        "name": "limit",
        "in": "query",
        "schema": {
          "type": "integer",
          "default": 25,
          "maximum": 100
        },
        "description": "Items per page"
      },
      "Offset": {
        "name": "offset",
        "in": "query",
        "schema": {
          "type": "integer",
          "default": 0
        },
        "description": "Items to skip"
      },
      "XFapiInteractionId": {
        "name": "x-fapi-interaction-id",
        "in": "header",
        "required": false,
        "description": "RFC4122 UUID used as a correlation ID. If provided, the server MUST echo it in the response x-fapi-interaction-id header. If not provided, the server MUST generate a fresh UUID.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "example": "550e8400-e29b-41d4-a716-446655440000"
        }
      },
      "XFapiCustomerIpAddress": {
        "name": "x-fapi-customer-ip-address",
        "in": "header",
        "required": false,
        "description": "The PSU's IP address if the PSU is currently logged in with the TPP.",
        "schema": {
          "type": "string",
          "format": "ipv4",
          "example": "104.10.10.1"
        }
      },
      "XFapiAuthDate": {
        "name": "x-fapi-auth-date",
        "in": "header",
        "required": false,
        "description": "The time when the PSU last logged in with the TPP. RFC7231 HTTP-date format.",
        "schema": {
          "type": "string",
          "example": "Tue, 11 Sep 2024 08:42:00 UTC"
        }
      },
      "PageParam": {
        "name": "page",
        "in": "query",
        "required": false,
        "description": "Page number (1-based). Defaults to 1.",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "default": 1,
          "example": 1
        }
      },
      "LimitParam": {
        "name": "limit",
        "in": "query",
        "required": false,
        "description": "Number of items per page. Maximum 100. Defaults to 20.",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 100,
          "default": 20,
          "example": 20
        }
      },
      "CursorParam": {
        "name": "cursor",
        "in": "query",
        "required": false,
        "description": "Opaque cursor from a previous response for cursor-based pagination. Mutually exclusive with page.",
        "schema": {
          "type": "string",
          "example": "eyJpZCI6IjEyMyJ9"
        }
      },
      "StartingAfter": {
        "name": "starting_after",
        "in": "query",
        "required": false,
        "description": "Cursor for pagination. Returns results immediately after the supplied object id. Mutually exclusive with `ending_before`. Offset-style `offset` is also accepted for backward compatibility.",
        "schema": {
          "type": "string",
          "maxLength": 128
        }
      },
      "EndingBefore": {
        "name": "ending_before",
        "in": "query",
        "required": false,
        "description": "Cursor for pagination. Returns results immediately before the supplied object id. Mutually exclusive with `starting_after`.",
        "schema": {
          "type": "string",
          "maxLength": 128
        }
      },
      "RequestId": {
        "name": "X-Request-ID",
        "in": "header",
        "required": false,
        "description": "Client-supplied correlation id (UUID v4 recommended). Echoed back in the `X-Request-ID` response header and persisted across edge functions, ledger writes and outbound webhook deliveries for distributed tracing.",
        "schema": {
          "type": "string",
          "maxLength": 64,
          "pattern": "^[A-Za-z0-9._-]{1,64}$"
        }
      },
      "BudgetingLangQuery": {
        "name": "lang",
        "in": "query",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "en",
            "fr",
            "pid"
          ],
          "default": "en"
        },
        "description": "Response language for budgeting insights."
      },
      "Traceparent": {
        "name": "traceparent",
        "in": "header",
        "required": false,
        "description": "W3C Trace Context Level 2 traceparent header. When supplied, KOB propagates the same context to every upstream call (bank connectors, mobile-money providers, settlement workers) and emits the resulting span IDs to OTLP collectors. See https://www.w3.org/TR/trace-context/",
        "schema": {
          "type": "string",
          "pattern": "^[0-9a-f]{2}-[0-9a-f]{32}-[0-9a-f]{16}-[0-9a-f]{2}$",
          "maxLength": 55
        },
        "example": "00-0af7651916cd43dd8448eb211c80319c-b7ad6b7169203331-01"
      },
      "Tracestate": {
        "name": "tracestate",
        "in": "header",
        "required": false,
        "description": "W3C Trace Context Level 2 tracestate header. Vendor-specific trace data, propagated unchanged.",
        "schema": {
          "type": "string",
          "maxLength": 512
        },
        "example": "kob=req:abc123,partner=acme"
      },
      "AcceptLanguage": {
        "name": "Accept-Language",
        "in": "header",
        "required": false,
        "description": "BCP 47 language tag(s) for response localisation. Supported: `en`, `en-CM`, `en-GB`, `fr`, `fr-CM`. Defaults to `en` when omitted. RFC 7807 `ProblemDetails.detail` and `title` are translated when a French tag is supplied.",
        "schema": {
          "type": "string",
          "example": "fr-CM",
          "pattern": "^[A-Za-z]{2,3}(-[A-Za-z]{2})?(,[A-Za-z]{2,3}(-[A-Za-z]{2})?(;q=0\\.[0-9]+)?)*$"
        }
      },
      "IdempotencyKeyHeader": {
        "name": "Idempotency-Key",
        "in": "header",
        "required": false,
        "schema": {
          "type": "string",
          "format": "uuid",
          "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$",
          "maxLength": 255
        },
        "description": "Optional UUID v4 idempotency key (draft-ietf-httpapi-idempotency-key-header §2). When supplied, KOB scopes the key by tenant + route + method and replays the original response for identical retries, returns 409 IDEMPOTENCY_KEY_REUSED for the same key with a different request body, and returns 409 IDEMPOTENCY_REQUEST_IN_PROGRESS for concurrent duplicates. Retention: 24h. Existing v1 clients that omit the header retain prior behaviour (Phase 1B backward-compatible additive rollout)."
      },
      "WebhookSignatureV2Header": {
        "name": "X-Webhook-Signature",
        "in": "header",
        "required": true,
        "description": "Webhooks v2 signature in the form `t=<unix-seconds>,v1=<hex>`. `v1` is the lowercase hex HMAC-SHA256 of the string `<t>.<raw request body>` keyed with the endpoint signing secret. Compare with a constant-time function and reject the request when `|now - t| > 300` seconds. Endpoints registered through the deprecated v1 webhook operations receive a raw lowercase hex HMAC-SHA256 of the body in this header instead.",
        "schema": {
          "type": "string",
          "example": "t=1760000000,v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bd"
        }
      },
      "WebhookTimestampHeader": {
        "name": "X-Webhook-Timestamp",
        "in": "header",
        "required": true,
        "description": "Unix time in seconds at which the delivery was signed. Equal to `t` in `X-Webhook-Signature`; part of the signed string.",
        "schema": {
          "type": "string",
          "pattern": "^[0-9]{10}$",
          "example": "1760000000"
        }
      },
      "WebhookIdHeader": {
        "name": "X-Webhook-ID",
        "in": "header",
        "required": true,
        "description": "Unique identifier of this delivery attempt (UUID). A new value is issued for each attempt, so it identifies the delivery, not the business event. Use `X-Webhook-Event-ID` for deduplication.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      "WebhookEventIdHeader": {
        "name": "X-Webhook-Event-ID",
        "in": "header",
        "required": false,
        "description": "Stable identifier of the logical event (UUID), generated server-side when the event is dispatched and identical on every retry and on every subscribed endpoint. Equal to `event_id` in the body. Store it for at least the retry horizon (about 72 hours) and acknowledge duplicates with 2xx without reprocessing. Absent only on retries of deliveries created before release 4.54.1.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      "WebhookEventHeader": {
        "name": "X-Webhook-Event",
        "in": "header",
        "required": true,
        "description": "Event type, identical to the `event` field in the body.",
        "schema": {
          "type": "string",
          "example": "charge.succeeded"
        }
      },
      "WebhookSignatureLegacyHeader": {
        "name": "X-Webhook-Signature-Legacy",
        "in": "header",
        "required": false,
        "description": "Deprecated. Lowercase hex HMAC-SHA256 of the raw body without a timestamp, sent alongside the v2 signature for receivers that have not migrated. Scheduled for removal in API v5.0.0. Do not rely on it for replay protection.",
        "schema": {
          "type": "string"
        }
      }
    },
    "headers": {
      "XFapiInteractionIdResponse": {
        "description": "RFC4122 UUID echoing the request x-fapi-interaction-id or a server-generated UUID if not provided in the request.",
        "required": true,
        "schema": {
          "type": "string",
          "format": "uuid",
          "example": "550e8400-e29b-41d4-a716-446655440000"
        }
      },
      "XRateLimitLimit": {
        "description": "The maximum number of requests allowed in the current rate limit window.",
        "schema": {
          "type": "integer",
          "example": 1000
        }
      },
      "XRateLimitRemaining": {
        "description": "The number of requests remaining in the current rate limit window.",
        "schema": {
          "type": "integer",
          "example": 995
        }
      },
      "XRateLimitReset": {
        "description": "UTC epoch seconds when the current rate limit window resets.",
        "schema": {
          "type": "integer",
          "example": 1743081600
        }
      },
      "RetryAfter": {
        "description": "Number of seconds to wait before retrying after a 429 Too Many Requests response. Implement exponential backoff with jitter starting from this value.",
        "schema": {
          "type": "integer",
          "example": 30
        }
      },
      "CacheControl": {
        "description": "Directives for caching mechanisms. For mutable data (balances, transactions): `no-cache`. For semi-static data (bank directory, exchange rates): `max-age=300, must-revalidate`.",
        "required": true,
        "schema": {
          "type": "string",
          "example": "max-age=300, must-revalidate"
        }
      },
      "ETag": {
        "description": "Entity tag for conditional requests. Use with `If-None-Match` on subsequent requests to receive 304 Not Modified when data has not changed.",
        "required": true,
        "schema": {
          "type": "string",
          "example": "\"v1-abc123def456\""
        }
      },
      "LastModified": {
        "description": "Timestamp of last data modification. Use with `If-Modified-Since` for conditional polling.",
        "required": false,
        "schema": {
          "type": "string",
          "format": "date-time",
          "example": "2026-05-02T10:15:30Z"
        }
      },
      "IdempotencyKey": {
        "description": "A unique UUID (v4) identifying this request for safe retries. Keys are retained for **24 hours** after the first request. Reusing a key with identical parameters returns the cached response. Reusing a key with different parameters returns 409 Conflict. Required on all money-moving POST endpoints.",
        "required": true,
        "schema": {
          "type": "string",
          "format": "uuid",
          "example": "550e8400-e29b-41d4-a716-446655440000",
          "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$",
          "maxLength": 255
        }
      },
      "X-RateLimit-Limit": {
        "description": "Maximum number of requests allowed in the current window",
        "schema": {
          "type": "integer",
          "example": 1000
        }
      },
      "X-RateLimit-Remaining": {
        "description": "Number of requests remaining in the current window",
        "schema": {
          "type": "integer",
          "example": 847
        }
      },
      "X-RateLimit-Reset": {
        "description": "Unix timestamp when the rate limit window resets",
        "schema": {
          "type": "integer",
          "example": 1709290800
        }
      },
      "Retry-After": {
        "description": "Seconds to wait before retrying (only on 429 responses)",
        "schema": {
          "type": "integer",
          "example": 30
        }
      },
      "XFapiInteractionId": {
        "description": "FAPI 1.0 §6.2.1.13 — server echoes (or generates) a UUID v4 correlation ID so callers can pin a single request across logs and audits.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      "X-Webhook-Replay": {
        "description": "Set to `true` when the event is a manual replay from the DLQ or operator console.",
        "schema": {
          "type": "boolean"
        }
      },
      "X-Webhook-Replay-Of": {
        "description": "UUID of the original delivery being replayed. Only present when `X-Webhook-Replay: true`.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      "X-Circuit-State": {
        "description": "Current circuit-breaker state for the receiving endpoint (`closed`, `half_open`, `open`). Echoed on every webhook attempt so receivers can self-throttle.",
        "schema": {
          "type": "string",
          "enum": [
            "closed",
            "half_open",
            "open"
          ]
        }
      },
      "X-Idempotent-Replay": {
        "description": "Set to `true` when the response was served from the idempotency cache for a replayed request (Stripe API Reference §Idempotent Requests).",
        "schema": {
          "type": "boolean"
        }
      },
      "X-Idempotency-Status": {
        "description": "Idempotency outcome: `first_request` (new key, normal processing), `replayed` (cached response served), `conflict_rejected` (same key reused with different payload — 409).",
        "schema": {
          "type": "string",
          "enum": [
            "first_request",
            "replayed",
            "conflict_rejected"
          ]
        }
      },
      "X-Webhook-Signature": {
        "description": "HMAC-SHA256 webhook signature. Format `t=<unix_ts>,v1=<hex>` per Stripe webhook signing convention. Receivers MUST reject deliveries where `|now - t| > 300s` (OWASP Webhook Security Cheat Sheet).",
        "schema": {
          "type": "string",
          "pattern": "^t=\\d{10},v1=[0-9a-f]{64}$",
          "example": "t=1716998400,v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bd"
        }
      },
      "X-Webhook-Timestamp": {
        "description": "Unix timestamp (seconds) of webhook signature generation. Use to compute and verify replay-protection window.",
        "schema": {
          "type": "integer",
          "format": "int64",
          "example": 1716998400
        }
      },
      "X-Webhook-Signature-Legacy": {
        "description": "Deprecated. Raw HMAC-SHA256 hex of the body without timestamp prefix. Emitted in parallel during the 4.42.0 deprecation window for receivers that have not yet adopted the timestamped signature. Will be removed in v5.0.0.",
        "deprecated": true,
        "schema": {
          "type": "string",
          "pattern": "^[0-9a-f]{64}$"
        }
      },
      "Traceparent": {
        "description": "Echoed W3C traceparent (Trace Context Level 2). Always returned to support distributed correlation.",
        "schema": {
          "type": "string",
          "pattern": "^[0-9a-f]{2}-[0-9a-f]{32}-[0-9a-f]{16}-[0-9a-f]{2}$"
        }
      },
      "X-Confirmation-Eta": {
        "description": "Server-estimated seconds until the underlying rail returns a terminal state. Echoes RtpSla.expected_completion_seconds for callers that prefer header-only signalling.",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 86400
        }
      },
      "Content-Language": {
        "description": "Language of the response body (BCP 47). Echoes the negotiated tag.",
        "schema": {
          "type": "string",
          "example": "fr"
        }
      },
      "Deprecation": {
        "description": "RFC 8594 Deprecation indicator. Date-time the resource was marked deprecated.",
        "schema": {
          "type": "string",
          "example": "Thu, 29 May 2026 00:00:00 GMT"
        }
      },
      "Sunset": {
        "description": "RFC 8594 Sunset header. Date-time the resource will be removed.",
        "schema": {
          "type": "string",
          "example": "Wed, 01 Jan 2027 00:00:00 GMT"
        }
      },
      "LinkSuccessor": {
        "description": "RFC 8288 Link header carrying rel=\"successor-version\" pointing to the replacement endpoint.",
        "schema": {
          "type": "string",
          "example": "<https://api.kangopenbanking.com/v1/verify/nin>; rel=\"successor-version\""
        }
      }
    },
    "responses": {
      "NotModified": {
        "description": "Resource has not been modified since the last request. Returned when `If-None-Match` matches the current `ETag` or `If-Modified-Since` is after `Last-Modified`.",
        "headers": {
          "ETag": {
            "$ref": "#/components/headers/ETag"
          },
          "Cache-Control": {
            "$ref": "#/components/headers/CacheControl"
          }
        }
      },
      "TooManyRequests": {
        "description": "429 Too Many Requests",
        "headers": {
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/XRateLimitLimit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/XRateLimitRemaining"
          },
          "X-RateLimit-Reset": {
            "$ref": "#/components/headers/XRateLimitReset"
          },
          "Retry-After": {
            "$ref": "#/components/headers/RetryAfter"
          }
        },
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/ProblemDetails"
            },
            "examples": {
              "default": {
                "$ref": "#/components/examples/ErrorRateLimited"
              }
            }
          },
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ProblemDetails"
            },
            "examples": {
              "default": {
                "$ref": "#/components/examples/ErrorRateLimited"
              }
            }
          }
        }
      },
      "Unauthorized": {
        "description": "401 Unauthorized",
        "headers": {},
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/ProblemDetails"
            },
            "examples": {
              "default": {
                "$ref": "#/components/examples/ErrorUnauthorized"
              }
            }
          },
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ProblemDetails"
            },
            "examples": {
              "default": {
                "$ref": "#/components/examples/ErrorUnauthorized"
              }
            }
          }
        }
      },
      "Forbidden": {
        "description": "403 Forbidden",
        "headers": {},
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/ProblemDetails"
            },
            "examples": {
              "default": {
                "$ref": "#/components/examples/ErrorForbidden"
              }
            }
          },
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ProblemDetails"
            },
            "examples": {
              "default": {
                "$ref": "#/components/examples/ErrorForbidden"
              }
            }
          }
        }
      },
      "Conflict": {
        "description": "409 Conflict",
        "headers": {},
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/ProblemDetails"
            },
            "examples": {
              "default": {
                "$ref": "#/components/examples/ErrorConflict"
              }
            }
          },
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ProblemDetails"
            },
            "examples": {
              "default": {
                "$ref": "#/components/examples/ErrorConflict"
              }
            }
          }
        }
      },
      "BadRequest": {
        "description": "400 Bad Request",
        "headers": {},
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/ProblemDetails"
            },
            "examples": {
              "default": {
                "$ref": "#/components/examples/ErrorBadRequest"
              }
            }
          },
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ProblemDetails"
            },
            "examples": {
              "default": {
                "$ref": "#/components/examples/ErrorBadRequest"
              }
            }
          }
        }
      },
      "NotFound": {
        "description": "404 Not Found",
        "headers": {},
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/ProblemDetails"
            },
            "examples": {
              "default": {
                "$ref": "#/components/examples/ErrorNotFound"
              }
            }
          },
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ProblemDetails"
            },
            "examples": {
              "default": {
                "$ref": "#/components/examples/ErrorNotFound"
              }
            }
          }
        }
      },
      "UnprocessableEntity": {
        "description": "422 Unprocessable Entity",
        "headers": {},
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/ProblemDetails"
            },
            "examples": {
              "default": {
                "$ref": "#/components/examples/ErrorUnprocessable"
              }
            }
          },
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ProblemDetails"
            },
            "examples": {
              "default": {
                "$ref": "#/components/examples/ErrorUnprocessable"
              }
            }
          }
        }
      },
      "InternalServerError": {
        "description": "500 Internal Server Error",
        "headers": {},
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/ProblemDetails"
            },
            "examples": {
              "default": {
                "$ref": "#/components/examples/ErrorServer"
              }
            }
          },
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ProblemDetails"
            },
            "examples": {
              "default": {
                "$ref": "#/components/examples/ErrorServer"
              }
            }
          }
        }
      },
      "ServiceUnavailable": {
        "description": "503 Service Unavailable",
        "headers": {},
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/ProblemDetails"
            },
            "examples": {
              "default": {
                "$ref": "#/components/examples/ErrorUnavailable"
              }
            }
          },
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ProblemDetails"
            },
            "examples": {
              "default": {
                "$ref": "#/components/examples/ErrorUnavailable"
              }
            }
          }
        }
      }
    },
    "examples": {
      "GenericSuccess": {
        "summary": "Successful response envelope",
        "value": {
          "success": true,
          "data": {
            "id": "obj_01HZX9TRJ4M7YQK6P3W2VBDN5K",
            "object": "resource",
            "created_at": "2026-05-02T10:15:30Z"
          },
          "meta": {
            "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
            "timestamp": "2026-05-02T10:15:30Z"
          }
        }
      },
      "PaginatedList": {
        "summary": "Cursor-paginated list",
        "value": {
          "success": true,
          "data": [
            {
              "id": "obj_01HZX9TRJ4M7YQK6P3W2VBDN5K",
              "object": "resource",
              "created_at": "2026-05-02T10:15:30Z"
            },
            {
              "id": "obj_01HZX9TRJ4M7YQK6P3W2VBDN5L",
              "object": "resource",
              "created_at": "2026-05-02T10:15:31Z"
            }
          ],
          "pagination": {
            "has_more": true,
            "next_cursor": "cursor_01HZX9TRJ4M7YQK6P3W2VBDN5M",
            "prev_cursor": null,
            "total_count": 247
          },
          "meta": {
            "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
            "timestamp": "2026-05-02T10:15:30Z"
          }
        }
      },
      "ErrorBadRequest": {
        "summary": "400 Bad Request",
        "value": {
          "type": "https://docs.kangopenbanking.com/errors/invalid_request",
          "title": "Bad Request",
          "status": 400,
          "code": "invalid_request",
          "detail": "The request body failed validation. See errors[] for field-level detail.",
          "instance": "https://api.kangopenbanking.com/v1/resource/01HZX9TRJ4M7YQK6P3W2VBDN5K",
          "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
          "timestamp": "2026-05-02T10:15:30Z"
        }
      },
      "ErrorUnauthorized": {
        "summary": "401 Unauthorized",
        "value": {
          "type": "https://docs.kangopenbanking.com/errors/invalid_credentials",
          "title": "Unauthorized",
          "status": 401,
          "code": "invalid_credentials",
          "detail": "Missing or invalid bearer token. Authenticate at /v1/oauth/token.",
          "instance": "https://api.kangopenbanking.com/v1/resource/01HZX9TRJ4M7YQK6P3W2VBDN5K",
          "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
          "timestamp": "2026-05-02T10:15:30Z"
        }
      },
      "ErrorForbidden": {
        "summary": "403 Forbidden",
        "value": {
          "type": "https://docs.kangopenbanking.com/errors/insufficient_scope",
          "title": "Forbidden",
          "status": 403,
          "code": "insufficient_scope",
          "detail": "The access token is missing the required scope for this operation.",
          "instance": "https://api.kangopenbanking.com/v1/resource/01HZX9TRJ4M7YQK6P3W2VBDN5K",
          "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
          "timestamp": "2026-05-02T10:15:30Z"
        }
      },
      "ErrorNotFound": {
        "summary": "404 Not Found",
        "value": {
          "type": "https://docs.kangopenbanking.com/errors/resource_not_found",
          "title": "Not Found",
          "status": 404,
          "code": "resource_not_found",
          "detail": "The requested resource does not exist or has been archived.",
          "instance": "https://api.kangopenbanking.com/v1/resource/01HZX9TRJ4M7YQK6P3W2VBDN5K",
          "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
          "timestamp": "2026-05-02T10:15:30Z"
        }
      },
      "ErrorConflict": {
        "summary": "409 Conflict",
        "value": {
          "type": "https://docs.kangopenbanking.com/errors/idempotency_conflict",
          "title": "Conflict",
          "status": 409,
          "code": "idempotency_conflict",
          "detail": "Idempotency-Key was reused with a different request body.",
          "instance": "https://api.kangopenbanking.com/v1/resource/01HZX9TRJ4M7YQK6P3W2VBDN5K",
          "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
          "timestamp": "2026-05-02T10:15:30Z"
        }
      },
      "ErrorUnprocessable": {
        "summary": "422 Unprocessable Entity",
        "value": {
          "type": "https://docs.kangopenbanking.com/errors/business_rule_violation",
          "title": "Unprocessable Entity",
          "status": 422,
          "code": "business_rule_violation",
          "detail": "The request was syntactically valid but violates a business rule (e.g. insufficient funds).",
          "instance": "https://api.kangopenbanking.com/v1/resource/01HZX9TRJ4M7YQK6P3W2VBDN5K",
          "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
          "timestamp": "2026-05-02T10:15:30Z"
        }
      },
      "ErrorRateLimited": {
        "summary": "429 Too Many Requests",
        "value": {
          "type": "https://docs.kangopenbanking.com/errors/rate_limited",
          "title": "Too Many Requests",
          "status": 429,
          "code": "rate_limited",
          "detail": "Request quota exceeded. Retry after the period indicated by Retry-After.",
          "instance": "https://api.kangopenbanking.com/v1/resource/01HZX9TRJ4M7YQK6P3W2VBDN5K",
          "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
          "timestamp": "2026-05-02T10:15:30Z"
        }
      },
      "ErrorServer": {
        "summary": "500 Internal Server Error",
        "value": {
          "type": "https://docs.kangopenbanking.com/errors/internal_error",
          "title": "Internal Server Error",
          "status": 500,
          "code": "internal_error",
          "detail": "An unexpected error occurred. The incident has been logged with request_id.",
          "instance": "https://api.kangopenbanking.com/v1/resource/01HZX9TRJ4M7YQK6P3W2VBDN5K",
          "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
          "timestamp": "2026-05-02T10:15:30Z"
        }
      },
      "ErrorUnavailable": {
        "summary": "503 Service Unavailable",
        "value": {
          "type": "https://docs.kangopenbanking.com/errors/service_unavailable",
          "title": "Service Unavailable",
          "status": 503,
          "code": "service_unavailable",
          "detail": "A downstream dependency is temporarily unavailable. Retry with exponential backoff.",
          "instance": "https://api.kangopenbanking.com/v1/resource/01HZX9TRJ4M7YQK6P3W2VBDN5K",
          "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
          "timestamp": "2026-05-02T10:15:30Z"
        }
      },
      "PaymentIntentCreated": {
        "summary": "Payment intent created",
        "value": {
          "success": true,
          "data": {
            "id": "pi_01HZX9TRJ4M7YQK6P3W2VBDN5K",
            "object": "payment_intent",
            "amount": "5000",
            "currency": "XAF",
            "status": "requires_confirmation",
            "client_secret": "pi_01HZX9TRJ4M7YQK6P3W2VBDN5K_secret_aBc123",
            "payment_method_types": [
              "mobile_money",
              "card",
              "bank_transfer"
            ],
            "idempotency_key": "550e8400-e29b-41d4-a716-446655440000",
            "created_at": "2026-05-02T10:15:30Z"
          },
          "meta": {
            "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
            "timestamp": "2026-05-02T10:15:30Z"
          }
        }
      },
      "AccountBalance": {
        "summary": "Account balance snapshot",
        "value": {
          "success": true,
          "data": {
            "account_id": "acc_01HZX9TRJ4M7YQK6P3W2VBDN5K",
            "currency": "XAF",
            "balances": [
              {
                "type": "ClosingAvailable",
                "amount": "125000",
                "credit_debit_indicator": "Credit",
                "datetime": "2026-05-02T10:15:30Z"
              },
              {
                "type": "ClosingBooked",
                "amount": "130000",
                "credit_debit_indicator": "Credit",
                "datetime": "2026-05-02T10:15:30Z"
              }
            ]
          },
          "meta": {
            "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
            "timestamp": "2026-05-02T10:15:30Z"
          }
        }
      },
      "ProblemDetailsConflict": {
        "summary": "RFC 7807 — idempotency key reused with different payload (409)",
        "value": {
          "type": "https://api.kangopenbanking.com/errors/idempotency-key-reused",
          "title": "Idempotency Key Conflict",
          "status": 409,
          "detail": "The provided Idempotency-Key was previously used with a different request body.",
          "instance": "https://api.kangopenbanking.com/v1/gateway/charges",
          "error_id": "err_idem_a1b2c3",
          "timestamp": "2026-05-29T10:00:00Z"
        }
      },
      "ProblemDetailsValidation": {
        "summary": "RFC 7807 — request body validation error (422)",
        "value": {
          "type": "https://api.kangopenbanking.com/errors/validation",
          "title": "Unprocessable Entity",
          "status": 422,
          "detail": "One or more request fields failed validation.",
          "instance": "https://api.kangopenbanking.com/v1/gateway/charges",
          "error_id": "err_val_d4e5f6",
          "timestamp": "2026-05-29T10:00:00Z",
          "errors": [
            {
              "field": "amount",
              "code": "GW_001",
              "message": "Amount must be > 0"
            },
            {
              "field": "currency",
              "code": "GW_002",
              "message": "Unsupported currency 'USX'"
            }
          ]
        }
      },
      "ProblemDetailsRateLimited": {
        "summary": "RFC 7807 — rate limit exceeded (429)",
        "value": {
          "type": "https://api.kangopenbanking.com/errors/rate-limited",
          "title": "Too Many Requests",
          "status": 429,
          "detail": "Request rate exceeded for the merchant's current tier.",
          "instance": "https://api.kangopenbanking.com/v1/gateway/charges",
          "error_id": "err_rl_g7h8i9",
          "timestamp": "2026-05-29T10:00:00Z",
          "retry_after": 30
        }
      },
      "MobileMoneyInsufficientFunds": {
        "summary": "Provider declined for insufficient funds",
        "value": {
          "provider": "mtn",
          "raw_code": "NOT_ENOUGH_FUNDS",
          "raw_message": "Subscriber balance too low",
          "normalized_code": "insufficient_funds",
          "retryable": false
        }
      },
      "ProblemDetailsSystemCategoryProtected": {
        "summary": "Protected system category cannot be soft-deleted",
        "value": {
          "type": "https://api.kangopenbanking.com/errors/system-category-protected",
          "title": "System Category Protected",
          "status": 409,
          "detail": "The requested category is a system-managed category and cannot be soft-deleted.",
          "instance": "https://api.kangopenbanking.com/v1/budgeting/categories/00000000-0000-4000-8000-000000000000",
          "code": "SYSTEM_CATEGORY_PROTECTED",
          "error_id": "err_syscat_a1b2c3",
          "timestamp": "2026-07-16T10:00:00Z"
        }
      },
      "ProblemDetailsCategoryActiveDependencies": {
        "summary": "Category has active dependencies preventing soft-deletion",
        "value": {
          "type": "https://api.kangopenbanking.com/errors/category-has-active-dependencies",
          "title": "Category Has Active Dependencies",
          "status": 409,
          "detail": "The category cannot be soft-deleted because active dependent resources still reference it.",
          "instance": "https://api.kangopenbanking.com/v1/budgeting/categories/00000000-0000-4000-8000-000000000000",
          "code": "CATEGORY_HAS_ACTIVE_DEPENDENCIES",
          "error_id": "err_catdep_a1b2c3",
          "timestamp": "2026-07-16T10:00:00Z"
        }
      },
      "ProblemDetailsIdempotencyKeyReused": {
        "summary": "Idempotency key reused with a different request body",
        "value": {
          "type": "https://api.kangopenbanking.com/errors/idempotency-key-reused",
          "title": "Idempotency Key Conflict",
          "status": 409,
          "detail": "The provided Idempotency-Key was previously used with a different request body.",
          "instance": "https://api.kangopenbanking.com/v1/budgeting/budgets/00000000-0000-4000-8000-000000000000",
          "code": "IDEMPOTENCY_KEY_REUSED",
          "error_id": "err_idem_a1b2c3",
          "timestamp": "2026-07-16T10:00:00Z"
        }
      },
      "ProblemDetailsInvalidIdempotencyKey": {
        "summary": "Malformed Idempotency-Key header",
        "value": {
          "type": "https://api.kangopenbanking.com/errors/invalid-idempotency-key",
          "title": "Invalid Idempotency Key",
          "status": 400,
          "detail": "The Idempotency-Key header value is not a valid UUID v4.",
          "instance": "https://api.kangopenbanking.com/v1/budgeting/budgets/00000000-0000-4000-8000-000000000000",
          "code": "INVALID_IDEMPOTENCY_KEY",
          "error_id": "err_iik_a1b2c3",
          "timestamp": "2026-07-16T10:00:00Z"
        }
      },
      "ProblemDetailsGoalHasPendingFinancialOperations": {
        "summary": "Goal has unresolved financial operations and cannot be archived",
        "value": {
          "type": "https://api.kangopenbanking.com/errors/goal-has-pending-financial-operations",
          "title": "Goal Has Pending Financial Operations",
          "status": 409,
          "detail": "The savings goal cannot be archived while it has unresolved contributions, transfers, settlements, payment instructions or round-up instructions.",
          "instance": "https://api.kangopenbanking.com/v1/budgeting/goals/00000000-0000-4000-8000-000000000000",
          "code": "GOAL_HAS_PENDING_FINANCIAL_OPERATIONS",
          "error_id": "err_goalpend_a1b2c3",
          "timestamp": "2026-07-16T10:00:00Z"
        }
      },
      "ProblemDetailsGoalStateConflict": {
        "summary": "Goal lifecycle state does not permit archival",
        "value": {
          "type": "https://api.kangopenbanking.com/errors/goal-state-conflict",
          "title": "Goal State Conflict",
          "status": 409,
          "detail": "The savings goal is in a lifecycle state that does not permit archival.",
          "instance": "https://api.kangopenbanking.com/v1/budgeting/goals/00000000-0000-4000-8000-000000000000",
          "code": "GOAL_STATE_CONFLICT",
          "error_id": "err_goalstate_a1b2c3",
          "timestamp": "2026-07-16T10:00:00Z"
        }
      },
      "ProblemDetailsRoundupHasPendingInstructions": {
        "summary": "Round-up has pending instructions preventing disablement",
        "value": {
          "type": "https://api.kangopenbanking.com/errors/roundup-has-pending-instructions",
          "title": "Round-Up Has Pending Instructions",
          "status": 409,
          "detail": "Round-up cannot be disabled while pending round-up instructions remain unresolved.",
          "instance": "https://api.kangopenbanking.com/v1/budgeting/goals/00000000-0000-4000-8000-000000000000/round-up",
          "code": "ROUNDUP_HAS_PENDING_INSTRUCTIONS",
          "error_id": "err_ruspend_a1b2c3",
          "timestamp": "2026-07-16T10:00:00Z"
        }
      },
      "ProblemDetailsRoundupStateConflict": {
        "summary": "Round-up configuration is in a state that cannot be disabled immediately",
        "value": {
          "type": "https://api.kangopenbanking.com/errors/roundup-state-conflict",
          "title": "Round-Up State Conflict",
          "status": 409,
          "detail": "Round-up cannot be disabled from its current state.",
          "instance": "https://api.kangopenbanking.com/v1/budgeting/goals/00000000-0000-4000-8000-000000000000/round-up",
          "code": "ROUNDUP_STATE_CONFLICT",
          "error_id": "err_rustate_a1b2c3",
          "timestamp": "2026-07-16T10:00:00Z"
        }
      }
    }
  },
  "paths": {
    "/healthz": {
      "get": {
        "tags": [
          "Monitoring"
        ],
        "summary": "Security posture self-verification",
        "description": "Reviewer-friendly snapshot of the API's live security posture: OAuth 2.0, OIDC, mTLS (FAPI 1.0 Advanced / RFC 8705), DCR (RFC 7591), PAR (RFC 9126), JAR (RFC 9101), PKCE (RFC 7636 — S256), webhook signing, JWKS rotation, and sandbox status. Returns 200 with cache-control public, max-age=60. No authentication required.",
        "operationId": "securityHealthz",
        "security": [],
        "responses": {
          "200": {
            "description": "Live security posture snapshot",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionId"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request — validation failed or malformed input.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests",
            "headers": {
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/healthz\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/healthz',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/healthz\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/healthz',\n]);\n\nprint_r($response->data);"
          }
        ],
        "x-public-endpoint": true,
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ]
      }
    },
    "/v1/health": {
      "get": {
        "tags": [
          "Monitoring"
        ],
        "summary": "API health check",
        "operationId": "apiHealth",
        "security": [],
        "responses": {
          "200": {
            "description": "API is healthy",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/StandardResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/HealthStatus"
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Successful response envelope",
                    "value": {
                      "data": {
                        "status": "healthy",
                        "version": "1.0.0",
                        "timestamp": "2026-05-02T10:15:30Z",
                        "id": "obj_01HZX9TRJ4M7YQK6P3W2VBDN5K",
                        "object": "resource",
                        "created_at": "2026-05-02T10:15:30Z"
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request — validation failed or malformed input.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          },
          "429": {
            "description": "Too Many Requests — rate limit exceeded.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          },
          "503": {
            "description": "API is unhealthy",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnavailable"
                  }
                }
              }
            },
            "headers": {
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          }
        },
        "description": "API health check.\n\n**Tag:** Monitoring\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/health\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/health',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/health\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/health',\n]);\n\nprint_r($response->data);"
          }
        ],
        "x-public-endpoint": true,
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ]
      }
    },
    "/v1/ready": {
      "get": {
        "tags": [
          "Monitoring"
        ],
        "summary": "Readiness probe",
        "description": "Returns 200 when the API is ready to accept traffic. Checks database connectivity.",
        "operationId": "apiReady",
        "security": [],
        "responses": {
          "200": {
            "description": "Ready",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ready": {
                      "type": "boolean"
                    },
                    "db": {
                      "type": "string"
                    },
                    "timestamp": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request — validation failed or malformed input.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          },
          "429": {
            "description": "Too Many Requests — rate limit exceeded.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          },
          "503": {
            "description": "Not ready",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnavailable"
                  }
                }
              }
            },
            "headers": {
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/ready\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/ready',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/ready\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/ready',\n]);\n\nprint_r($response->data);"
          }
        ],
        "x-public-endpoint": true,
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ]
      }
    },
    "/v1/system-health": {
      "get": {
        "tags": [
          "Monitoring"
        ],
        "summary": "Detailed system health",
        "operationId": "systemHealth",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "System health details",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/StandardResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/HealthStatus"
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Successful response envelope",
                    "value": {
                      "data": {
                        "status": "healthy",
                        "version": "1.0.0",
                        "timestamp": "2026-05-02T10:15:30Z",
                        "id": "obj_01HZX9TRJ4M7YQK6P3W2VBDN5K",
                        "object": "resource",
                        "created_at": "2026-05-02T10:15:30Z"
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Detailed system health.\n\n**Tag:** Monitoring\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/system-health\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/system-health',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/system-health\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/system-health',\n]);\n\nprint_r($response->data);"
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ]
      }
    },
    "/v1/oauth/authorize": {
      "get": {
        "tags": [
          "OAuth"
        ],
        "summary": "Authorize OAuth request",
        "description": "Authorize OAuth request.\n\n**Tag:** OAuth\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "operationId": "oauthAuthorize",
        "security": [],
        "parameters": [
          {
            "name": "response_type",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "code"
              ]
            }
          },
          {
            "name": "client_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "redirect_uri",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "scope",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "openid accounts payments"
          },
          {
            "name": "state",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "code_challenge",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "required": true,
            "description": "PKCE code challenge. The Base64URL-encoded SHA-256 hash of the code_verifier (S256 method). REQUIRED by FAPI 1.0 Advanced Section 5.2.2 for all authorization requests. The corresponding code_verifier must be provided at the token endpoint."
          },
          {
            "name": "code_challenge_method",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "S256"
              ]
            },
            "required": true,
            "description": "PKCE code challenge method. MUST be S256 (SHA-256). Plain method is NOT supported per FAPI 1.0 Advanced security requirements."
          },
          {
            "name": "nonce",
            "in": "query",
            "required": true,
            "description": "Cryptographically random nonce value associating the client session with the ID Token and preventing replay attacks. REQUIRED by FAPI 1.0 Advanced Section 5.2.2-14 for all authorization requests. Must be unique per request with at least 128 bits of entropy (minimum 22 Base64url characters). The server MUST include the nonce claim in the issued ID Token.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "request_uri",
            "in": "query",
            "required": false,
            "description": "FAPI 1.0 Advanced: URI referencing a Pushed Authorization Request (PAR). Mutually exclusive with request.",
            "schema": {
              "type": "string",
              "format": "uri"
            }
          },
          {
            "name": "request",
            "in": "query",
            "required": false,
            "description": "FAPI 1.0 Advanced: Signed JWT containing the authorization request parameters (Request Object). Mutually exclusive with request_uri.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "acr_values",
            "in": "query",
            "required": false,
            "description": "Space-separated string of requested Authentication Context Class Reference values. e.g. \"urn:openbanking:psd2:sca\"",
            "schema": {
              "type": "string",
              "example": "urn:openbanking:psd2:sca"
            }
          },
          {
            "name": "claims",
            "in": "query",
            "required": false,
            "description": "JSON object requesting specific claims in the ID Token or UserInfo response (OIDC Core Section 5.5).",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "302": {
            "description": "Redirect to authorization page",
            "headers": {
              "Location": {
                "schema": {
                  "type": "string",
                  "format": "uri"
                },
                "description": "Authorization page URL"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {}
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/oauth/authorize\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/oauth/authorize',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/oauth/authorize\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/oauth/authorize',\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/oauth/token": {
      "post": {
        "tags": [
          "OAuth"
        ],
        "summary": "Exchange authorization code for token",
        "operationId": "oauthToken",
        "security": [
          {
            "privateKeyJwt": []
          },
          {
            "mtls": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "required": [
                  "grant_type",
                  "client_id"
                ],
                "properties": {
                  "grant_type": {
                    "type": "string",
                    "enum": [
                      "authorization_code",
                      "refresh_token",
                      "client_credentials"
                    ],
                    "description": "OAuth 2.0 grant type"
                  },
                  "code": {
                    "type": "string",
                    "description": "Authorization code (required for authorization_code grant)"
                  },
                  "client_id": {
                    "type": "string"
                  },
                  "client_secret": {
                    "type": "string",
                    "description": "Client secret (required for client_credentials and refresh_token grants)"
                  },
                  "redirect_uri": {
                    "type": "string"
                  },
                  "code_verifier": {
                    "type": "string",
                    "description": "PKCE code verifier (required when code_challenge was used)"
                  },
                  "refresh_token": {
                    "type": "string",
                    "description": "Refresh token (required for refresh_token grant)"
                  },
                  "scope": {
                    "type": "string",
                    "description": "Space-delimited list of scopes (e.g. \"accounts payments\")",
                    "example": "accounts payments"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Token issued",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "access_token": {
                      "type": "string"
                    },
                    "token_type": {
                      "type": "string",
                      "example": "Bearer"
                    },
                    "expires_in": {
                      "type": "integer",
                      "example": 3600
                    },
                    "refresh_token": {
                      "type": "string"
                    },
                    "scope": {
                      "type": "string",
                      "example": "openid accounts"
                    }
                  }
                },
                "example": {
                  "access_token": "eyJ...token",
                  "token_type": "Bearer",
                  "expires_in": 3600,
                  "refresh_token": "rf_abc123",
                  "scope": "openid accounts"
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "OAuth 2.0 Token Endpoint. Supports two client authentication modes: (1) Public clients using authorization_code + PKCE — no client authentication required, use an empty security context. (2) Confidential clients using mTLS (RFC 8705) — present the client certificate registered via /v1/certificates for certificate-bound access tokens required by FAPI 1.0 Advanced.  Supports mutual TLS (mTLS) client authentication per RFC 8705 for certificate-bound access tokens required by FAPI 1.0 Advanced.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/oauth/token\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/oauth/token',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/oauth/token\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/oauth/token',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ]
      }
    },
    "/v1/oauth/introspect": {
      "post": {
        "tags": [
          "OAuth"
        ],
        "summary": "Introspect access token",
        "operationId": "oauthIntrospect",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "required": [
                  "token"
                ],
                "properties": {
                  "token": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Token introspection result",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "active": {
                      "type": "boolean"
                    },
                    "scope": {
                      "type": "string"
                    },
                    "client_id": {
                      "type": "string"
                    },
                    "exp": {
                      "type": "integer"
                    },
                    "sub": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Introspect access token.\n\n**Tag:** OAuth\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/oauth/introspect\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/oauth/introspect',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/oauth/introspect\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/oauth/introspect',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ]
      }
    },
    "/v1/oauth/par": {
      "post": {
        "tags": [
          "OAuth"
        ],
        "summary": "Pushed Authorization Request",
        "operationId": "parEndpoint",
        "security": [
          {
            "mtls": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "required": [
                  "client_id",
                  "response_type",
                  "redirect_uri",
                  "scope"
                ],
                "properties": {
                  "client_id": {
                    "type": "string"
                  },
                  "response_type": {
                    "type": "string"
                  },
                  "redirect_uri": {
                    "type": "string"
                  },
                  "scope": {
                    "type": "string"
                  },
                  "state": {
                    "type": "string"
                  },
                  "code_challenge": {
                    "type": "string"
                  },
                  "code_challenge_method": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "PAR created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "request_uri": {
                      "type": "string"
                    },
                    "expires_in": {
                      "type": "integer",
                      "example": 600
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Pushed Authorization Request.\n\n**Tag:** OAuth\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/oauth/par\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/oauth/par',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/oauth/par\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/oauth/par',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/dcr/register": {
      "post": {
        "tags": [
          "OAuth"
        ],
        "summary": "Dynamic Client Registration",
        "operationId": "dcrRegister",
        "security": [
          {
            "mtls": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DcrRegistrationRequest"
              },
              "example": {
                "client_name": "FinTech App Cameroun",
                "redirect_uris": [
                  "https://app.example.com/callback"
                ],
                "token_endpoint_auth_method": "client_secret_basic",
                "software_statement": "eyJhbGciOiJQUzI1NiJ9.eyJzb2Z0d2FyZV9pZCI6InRwcF8wMDEiLCJzb2Z0d2FyZV9jbGllbnRfbmFtZSI6IkZpblRlY2ggQXBwIENhbWVyb3VuIiwic29mdHdhcmVfcm9sZXMiOlsiQUlTUCIsIlBJU1AiXX0.sig",
                "grant_types": [
                  "authorization_code",
                  "refresh_token"
                ],
                "scope": "accounts payments"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Client registered",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DcrRegistrationResponse"
                },
                "example": {
                  "client_id": "tpp_a1b2c3d4-e5f6-7890-abcd-ef1234567890",
                  "client_secret": "kob_sec_7f3a9b2c4d5e6f1a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f",
                  "client_name": "FinTech App Cameroun",
                  "software_id": "tpp_001",
                  "software_roles": [
                    "AISP",
                    "PISP"
                  ],
                  "redirect_uris": [
                    "https://app.example.com/callback"
                  ],
                  "grant_types": [
                    "authorization_code",
                    "refresh_token"
                  ],
                  "response_types": [
                    "code"
                  ],
                  "token_endpoint_auth_method": "client_secret_basic",
                  "scope": "accounts payments",
                  "environment": "sandbox",
                  "client_id_issued_at": 1710504000
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Dynamic Client Registration.\n\n**Tag:** OAuth\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/dcr/register\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/dcr/register',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/dcr/register\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/dcr/register',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/oidc/.well-known/openid-configuration": {
      "get": {
        "tags": [
          "OAuth"
        ],
        "summary": "OIDC discovery",
        "operationId": "oidcConfig",
        "security": [],
        "responses": {
          "200": {
            "description": "OIDC configuration document",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "issuer": {
                      "type": "string"
                    },
                    "authorization_endpoint": {
                      "type": "string"
                    },
                    "token_endpoint": {
                      "type": "string"
                    },
                    "jwks_uri": {
                      "type": "string"
                    },
                    "response_types_supported": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "subject_types_supported": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "id_token_signing_alg_values_supported": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "userinfo_endpoint": {
                      "type": "string",
                      "example": "https://api.kangopenbanking.com/v1/oauth/userinfo",
                      "description": "URL of the UserInfo Endpoint (OIDC Core 1.0 Section 5.3)"
                    },
                    "registration_endpoint": {
                      "type": "string",
                      "example": "https://api.kangopenbanking.com/v1/dcr/register",
                      "description": "URL of the Dynamic Client Registration endpoint (RFC 7591)"
                    },
                    "scopes_supported": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "example": [
                        "openid",
                        "accounts",
                        "balances",
                        "transactions",
                        "payments",
                        "offline_access"
                      ],
                      "description": "List of OAuth 2.0 scope values supported"
                    },
                    "claims_supported": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "example": [
                        "sub",
                        "iss",
                        "auth_time",
                        "acr",
                        "name",
                        "given_name",
                        "family_name",
                        "email",
                        "phone_number"
                      ],
                      "description": "List of claim names supported in issued ID Tokens"
                    },
                    "token_endpoint_auth_methods_supported": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "example": [
                        "private_key_jwt",
                        "tls_client_auth",
                        "client_secret_basic"
                      ],
                      "description": "List of client authentication methods supported at the token endpoint. private_key_jwt required for FAPI 1.0 Advanced."
                    },
                    "request_object_signing_alg_values_supported": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "example": [
                        "PS256",
                        "ES256"
                      ],
                      "description": "Signing algorithms supported for Request Objects. PS256 required for FAPI 1.0 Advanced."
                    },
                    "token_endpoint_auth_signing_alg_values_supported": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "example": [
                        "PS256",
                        "ES256"
                      ],
                      "description": "Signing algorithms supported for JWT client authentication at the token endpoint."
                    },
                    "grant_types_supported": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "example": [
                        "authorization_code",
                        "refresh_token",
                        "client_credentials"
                      ],
                      "description": "List of OAuth 2.0 grant type values supported"
                    },
                    "require_pushed_authorization_requests": {
                      "type": "boolean",
                      "example": true,
                      "description": "If true, PAR (Pushed Authorisation Requests) are required. Required for FAPI 1.0 Advanced."
                    },
                    "mtls_endpoint_aliases": {
                      "type": "object",
                      "description": "mTLS endpoint aliases for certificate-bound access tokens (RFC 8705)",
                      "properties": {
                        "token_endpoint": {
                          "type": "string",
                          "example": "https://api.kangopenbanking.com/v1/oauth/token"
                        },
                        "par_endpoint": {
                          "type": "string",
                          "example": "https://api.kangopenbanking.com/v1/oauth/par"
                        }
                      }
                    },
                    "pushed_authorization_request_endpoint": {
                      "type": "string",
                      "format": "uri",
                      "description": "URL of the Pushed Authorisation Request (PAR) endpoint (RFC 9126). Clients SHOULD use PAR before calling the authorization endpoint.",
                      "example": "https://api.kangopenbanking.com/v1/oauth/par"
                    },
                    "backchannel_authentication_endpoint": {
                      "type": "string",
                      "format": "uri",
                      "description": "URL of the CIBA (Client-Initiated Backchannel Authentication) endpoint for decoupled authentication flows. Optional advanced FAPI feature for mobile banking step-up authentication.",
                      "example": "https://api.kangopenbanking.com/v1/auth/backchannel"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request — validation failed or malformed input.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          },
          "429": {
            "description": "Too Many Requests — rate limit exceeded.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          }
        },
        "description": "OIDC discovery.\n\n**Tag:** OAuth\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/oidc/.well-known/openid-configuration\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/oidc/.well-known/openid-configuration',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/oidc/.well-known/openid-configuration\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/oidc/.well-known/openid-configuration',\n]);\n\nprint_r($response->data);"
          }
        ],
        "x-public-endpoint": true,
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ]
      }
    },
    "/v1/jwks": {
      "get": {
        "tags": [
          "OAuth"
        ],
        "summary": "JSON Web Key Set",
        "operationId": "jwksEndpoint",
        "security": [],
        "responses": {
          "200": {
            "description": "Public keys for token verification",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "keys": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "kty": {
                            "type": "string"
                          },
                          "kid": {
                            "type": "string"
                          },
                          "use": {
                            "type": "string"
                          },
                          "n": {
                            "type": "string"
                          },
                          "e": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/PaginatedList"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request — validation failed or malformed input.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          },
          "429": {
            "description": "Too Many Requests — rate limit exceeded.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          }
        },
        "description": "JSON Web Key Set.\n\n**Tag:** OAuth\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.\n\n**Key selection:** select the verification key whose `kid` matches the JWT header `kid`; treat `kid` as an opaque string and refresh this document when an unknown `kid` is seen. The signing-key lifecycle derives `kid` as an RFC 7638 JWK thumbprint; key rotation is pending certification, so do not pin a single key.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/jwks\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/jwks',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/jwks\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/jwks',\n]);\n\nprint_r($response->data);"
          }
        ],
        "x-public-endpoint": true,
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          },
          {
            "$ref": "#/components/parameters/LimitParam"
          },
          {
            "$ref": "#/components/parameters/CursorParam"
          }
        ]
      }
    },
    "/v1/auth/phone/send-otp": {
      "post": {
        "tags": [
          "Authentication"
        ],
        "summary": "Send OTP to phone",
        "operationId": "phoneAuthSendOtp",
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "phone_number"
                ],
                "properties": {
                  "phone_number": {
                    "type": "string",
                    "example": "+237670000000"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OTP sent",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Send OTP to phone.\n\n**Tag:** Authentication\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/auth/phone/send-otp\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/auth/phone/send-otp',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/auth/phone/send-otp\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/auth/phone/send-otp',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ]
      }
    },
    "/v1/auth/phone/verify-otp": {
      "post": {
        "tags": [
          "Authentication"
        ],
        "summary": "Verify OTP",
        "operationId": "phoneAuthVerifyOtp",
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "phone_number",
                  "otp_code"
                ],
                "properties": {
                  "phone_number": {
                    "type": "string"
                  },
                  "otp_code": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Authentication successful",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "access_token": {
                      "type": "string"
                    },
                    "token_type": {
                      "type": "string",
                      "example": "Bearer"
                    },
                    "expires_in": {
                      "type": "integer",
                      "example": 3600
                    },
                    "refresh_token": {
                      "type": "string"
                    },
                    "user_id": {
                      "type": "string",
                      "format": "uuid"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Verify OTP.\n\n**Tag:** Authentication\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/auth/phone/verify-otp\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/auth/phone/verify-otp',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/auth/phone/verify-otp\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/auth/phone/verify-otp',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ]
      }
    },
    "/v1/auth/phone/pin-login": {
      "post": {
        "tags": [
          "Authentication"
        ],
        "summary": "Login with PIN",
        "operationId": "phoneAuthPinLogin",
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "phone_number",
                  "pin"
                ],
                "properties": {
                  "phone_number": {
                    "type": "string"
                  },
                  "pin": {
                    "type": "string",
                    "minLength": 4,
                    "maxLength": 6
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Authentication successful",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "access_token": {
                      "type": "string"
                    },
                    "token_type": {
                      "type": "string",
                      "example": "Bearer"
                    },
                    "expires_in": {
                      "type": "integer",
                      "example": 3600
                    },
                    "refresh_token": {
                      "type": "string"
                    },
                    "user_id": {
                      "type": "string",
                      "format": "uuid"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Login with PIN.\n\n**Tag:** Authentication\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/auth/phone/pin-login\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/auth/phone/pin-login',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/auth/phone/pin-login\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/auth/phone/pin-login',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ]
      }
    },
    "/v1/auth/pin/set": {
      "post": {
        "tags": [
          "Authentication"
        ],
        "summary": "Set PIN code",
        "operationId": "pinCodeSet",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "pin"
                ],
                "properties": {
                  "pin": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "PIN set",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Set PIN code.\n\n**Tag:** Authentication\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/auth/pin/set\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/auth/pin/set',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/auth/pin/set\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/auth/pin/set',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ]
      }
    },
    "/v1/auth/pin/verify": {
      "post": {
        "tags": [
          "Authentication"
        ],
        "summary": "Verify PIN code",
        "operationId": "pinCodeVerify",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "pin"
                ],
                "properties": {
                  "pin": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "PIN verified",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Verify PIN code.\n\n**Tag:** Authentication\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/auth/pin/verify\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/auth/pin/verify',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/auth/pin/verify\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/auth/pin/verify',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ]
      }
    },
    "/v1/auth/password/reset-with-pin": {
      "post": {
        "tags": [
          "Authentication"
        ],
        "summary": "Reset password with PIN",
        "operationId": "passwordResetWithPin",
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "phone_number",
                  "pin",
                  "new_password"
                ],
                "properties": {
                  "phone_number": {
                    "type": "string"
                  },
                  "pin": {
                    "type": "string"
                  },
                  "new_password": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Password reset",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Reset password with PIN.\n\n**Tag:** Authentication\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/auth/password/reset-with-pin\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/auth/password/reset-with-pin',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/auth/password/reset-with-pin\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/auth/password/reset-with-pin',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ]
      }
    },
    "/v1/security/captcha/generate": {
      "post": {
        "tags": [
          "Security"
        ],
        "summary": "Generate CAPTCHA",
        "operationId": "captchaGenerate",
        "security": [],
        "responses": {
          "200": {
            "description": "CAPTCHA challenge",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "challenge_id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "image_base64": {
                      "type": "string"
                    },
                    "question": {
                      "type": "string"
                    },
                    "expires_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Generate CAPTCHA.\n\n**Tag:** Security\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/security/captcha/generate\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/security/captcha/generate',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/security/captcha/generate\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/security/captcha/generate',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ]
      }
    },
    "/v1/security/captcha/verify": {
      "post": {
        "tags": [
          "Security"
        ],
        "summary": "Verify CAPTCHA",
        "operationId": "captchaVerify",
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "challenge_id",
                  "response"
                ],
                "properties": {
                  "challenge_id": {
                    "type": "string"
                  },
                  "response": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "CAPTCHA verified",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Verify CAPTCHA.\n\n**Tag:** Security\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/security/captcha/verify\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/security/captcha/verify',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/security/captcha/verify\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/security/captcha/verify',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ]
      }
    },
    "/v1/security/sca/initiate": {
      "post": {
        "tags": [
          "Security"
        ],
        "summary": "Initiate SCA",
        "operationId": "scaInitiate",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "action_type"
                ],
                "properties": {
                  "action_type": {
                    "type": "string",
                    "enum": [
                      "payment",
                      "consent",
                      "account_update"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "SCA challenge issued",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "challenge_id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "challenge_type": {
                      "type": "string",
                      "enum": [
                        "otp",
                        "biometric",
                        "pin"
                      ]
                    },
                    "expires_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Initiate SCA.\n\n**Tag:** Security\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/security/sca/initiate\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/security/sca/initiate',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/security/sca/initiate\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/security/sca/initiate',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ]
      }
    },
    "/v1/security/sca/verify": {
      "post": {
        "tags": [
          "Security"
        ],
        "summary": "Verify SCA",
        "operationId": "scaVerify",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "challenge_id",
                  "response"
                ],
                "properties": {
                  "challenge_id": {
                    "type": "string"
                  },
                  "response": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "SCA verified",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Verify SCA.\n\n**Tag:** Security\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/security/sca/verify\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/security/sca/verify',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/security/sca/verify\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/security/sca/verify',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ]
      }
    },
    "/v1/certificates": {
      "post": {
        "tags": [
          "Certificates"
        ],
        "summary": "Upload certificate",
        "operationId": "certificateUpload",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "certificate_pem"
                ],
                "properties": {
                  "certificate_pem": {
                    "type": "string"
                  },
                  "tpp_registration_id": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Certificate uploaded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Certificate"
                },
                "examples": {
                  "default": {
                    "summary": "Successful response envelope",
                    "value": {
                      "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                      "thumbprint": "thumbprint_value",
                      "subject_dn": "subject_dn_value",
                      "issuer_dn": "issuer_dn_value",
                      "success": true,
                      "data": {
                        "id": "obj_01HZX9TRJ4M7YQK6P3W2VBDN5K",
                        "object": "resource",
                        "created_at": "2026-05-02T10:15:30Z"
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      }
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Upload certificate.\n\n**Tag:** Certificates\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/certificates\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/certificates',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/certificates\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/certificates',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      },
      "get": {
        "tags": [
          "Certificates"
        ],
        "summary": "List certificates",
        "operationId": "certificateList",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "tpp_registration_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/PageParam"
          },
          {
            "$ref": "#/components/parameters/LimitParam"
          },
          {
            "$ref": "#/components/parameters/CursorParam"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Certificates list",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/Certificate"
                          }
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Cursor-paginated list",
                    "value": {
                      "data": [
                        {
                          "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "thumbprint": "thumbprint_value",
                          "subject_dn": "subject_dn_value",
                          "issuer_dn": "issuer_dn_value",
                          "object": "resource",
                          "created_at": "2026-05-02T10:15:30Z"
                        },
                        {
                          "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "thumbprint": "thumbprint_value",
                          "subject_dn": "subject_dn_value",
                          "issuer_dn": "issuer_dn_value",
                          "object": "resource",
                          "created_at": "2026-05-02T10:15:31Z"
                        }
                      ],
                      "pagination": {
                        "page": 1,
                        "limit": 20,
                        "total": 150,
                        "has_next": true,
                        "has_more": true,
                        "next_cursor": "cursor_01HZX9TRJ4M7YQK6P3W2VBDN5M",
                        "prev_cursor": null,
                        "total_count": 247
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "List certificates.\n\n**Tag:** Certificates\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/certificates\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/certificates',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/certificates\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/certificates',\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/certificates/revoke": {
      "post": {
        "tags": [
          "Certificates"
        ],
        "summary": "Revoke certificate",
        "operationId": "certificateRevoke",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "certificate_id",
                  "reason"
                ],
                "properties": {
                  "certificate_id": {
                    "type": "string"
                  },
                  "reason": {
                    "type": "string",
                    "enum": [
                      "key_compromise",
                      "ca_compromise",
                      "affiliation_changed",
                      "superseded",
                      "cessation_of_operation"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Certificate revoked",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Revoke certificate.\n\n**Tag:** Certificates\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/certificates/revoke\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/certificates/revoke',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/certificates/revoke\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/certificates/revoke',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/aisp/consents": {
      "post": {
        "tags": [
          "AISP"
        ],
        "summary": "Create AISP consent",
        "operationId": "aispCreateConsent",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "permissions",
                  "expiration_date"
                ],
                "properties": {
                  "permissions": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "ReadAccountsDetail",
                        "ReadBalances",
                        "ReadTransactionsDetail",
                        "ReadBeneficiariesDetail",
                        "ReadStandingOrdersDetail",
                        "ReadDirectDebitsDetail"
                      ]
                    },
                    "example": [
                      "ReadAccountsDetail",
                      "ReadBalances",
                      "ReadTransactionsDetail"
                    ]
                  },
                  "expiration_date": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "transaction_from_date": {
                    "type": "string",
                    "format": "date"
                  },
                  "transaction_to_date": {
                    "type": "string",
                    "format": "date"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Consent created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Consent"
                },
                "examples": {
                  "default": {
                    "summary": "Successful response envelope",
                    "value": {
                      "consent_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                      "status": "AwaitingAuthorisation",
                      "permissions": [
                        "permissions_value"
                      ],
                      "expiration_date": "2026-05-02T10:15:30Z",
                      "created_at": "2026-05-02T10:15:30Z",
                      "success": true,
                      "data": {
                        "id": "obj_01HZX9TRJ4M7YQK6P3W2VBDN5K",
                        "object": "resource",
                        "created_at": "2026-05-02T10:15:30Z"
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      }
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Create AISP consent.\n\n**Tag:** AISP\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/aisp/consents\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/aisp/consents',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/aisp/consents\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/aisp/consents',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/aisp/accounts": {
      "get": {
        "tags": [
          "AISP"
        ],
        "summary": "List accounts",
        "operationId": "aispAccounts",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "x-consent-id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Authorised AISP consent ID. Required for all account information endpoints."
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 25,
              "maximum": 100
            },
            "description": "Items per page"
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 0
            },
            "description": "Items to skip Legacy: kept for backwards compatibility — prefer starting_after/ending_before (see x-pagination)."
          },
          {
            "name": "sort_by",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "created_at"
            },
            "description": "Sort field"
          },
          {
            "name": "sort_order",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "asc",
                "desc"
              ],
              "default": "desc"
            },
            "description": "Sort direction"
          },
          {
            "$ref": "#/components/parameters/XFapiInteractionId"
          },
          {
            "$ref": "#/components/parameters/XFapiCustomerIpAddress"
          },
          {
            "$ref": "#/components/parameters/XFapiAuthDate"
          },
          {
            "name": "starting_after",
            "in": "query",
            "required": false,
            "description": "Cursor pagination — returns the page of results AFTER this resource id. Mutually exclusive with offset/ending_before. Preferred for new integrations (see x-pagination).",
            "schema": {
              "type": "string",
              "example": "acc_01HZQ..."
            }
          },
          {
            "name": "ending_before",
            "in": "query",
            "required": false,
            "description": "Cursor pagination — returns the page of results BEFORE this resource id. Mutually exclusive with offset/starting_after.",
            "schema": {
              "type": "string",
              "example": "acc_01HZQ..."
            }
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Accounts list",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/Account"
                          }
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Cursor-paginated list",
                    "value": {
                      "data": [
                        {
                          "account_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "account_type": "checking",
                          "account_subtype": "personal_current",
                          "currency": "XAF",
                          "identification_scheme": "LOCAL_BANK",
                          "identification_value": "identification_value_value",
                          "status": "active",
                          "id": "obj_01HZX9TRJ4M7YQK6P3W2VBDN5K",
                          "object": "resource",
                          "created_at": "2026-05-02T10:15:30Z"
                        },
                        {
                          "account_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "account_type": "checking",
                          "account_subtype": "personal_current",
                          "currency": "XAF",
                          "identification_scheme": "LOCAL_BANK",
                          "identification_value": "identification_value_value",
                          "status": "active",
                          "id": "obj_01HZX9TRJ4M7YQK6P3W2VBDN5L",
                          "object": "resource",
                          "created_at": "2026-05-02T10:15:31Z"
                        }
                      ],
                      "pagination": {
                        "page": 1,
                        "limit": 20,
                        "total": 150,
                        "has_next": true,
                        "has_more": true,
                        "next_cursor": "cursor_01HZX9TRJ4M7YQK6P3W2VBDN5M",
                        "prev_cursor": null,
                        "total_count": 247
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Pagination-Mode": {
                "description": "Either `cursor` or `offset` — echoes which mode the gateway interpreted.",
                "schema": {
                  "type": "string",
                  "enum": [
                    "cursor",
                    "offset"
                  ]
                }
              },
              "X-Pagination-Has-More": {
                "description": "Boolean (`true`/`false`) — whether more results are available.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Pagination-Next-Cursor": {
                "description": "Resource id to pass as `starting_after` for the next page (cursor mode only).",
                "schema": {
                  "type": "string"
                }
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "For banks using file-based connectors, account responses include `last_imported_at` (RFC 3339) and `data_source` (`file_connector|api_connector|manual`).",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/aisp/accounts\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/aisp/accounts',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/aisp/accounts\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/aisp/accounts',\n]);\n\nprint_r($response->data);"
          }
        ],
        "x-pagination-style": "cursor"
      }
    },
    "/v1/aisp/accounts/{accountId}": {
      "get": {
        "tags": [
          "AISP"
        ],
        "summary": "Get account details",
        "operationId": "aispAccountDetail",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "accountId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-consent-id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Authorised AISP consent ID. Required for all account information endpoints."
          },
          {
            "$ref": "#/components/parameters/XFapiInteractionId"
          },
          {
            "$ref": "#/components/parameters/XFapiCustomerIpAddress"
          },
          {
            "$ref": "#/components/parameters/XFapiAuthDate"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Account details",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/StandardResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/Account"
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Successful response envelope",
                    "value": {
                      "data": {
                        "account_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                        "account_type": "checking",
                        "account_subtype": "personal_current",
                        "currency": "XAF",
                        "identification_scheme": "LOCAL_BANK",
                        "identification_value": "identification_value_value",
                        "status": "active",
                        "id": "obj_01HZX9TRJ4M7YQK6P3W2VBDN5K",
                        "object": "resource",
                        "created_at": "2026-05-02T10:15:30Z"
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Get account details.\n\n**Tag:** AISP\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/aisp/accounts/{accountId}\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/aisp/accounts/{accountId}',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/aisp/accounts/{accountId}\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/aisp/accounts/{accountId}',\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/aisp/accounts/{accountId}/balances": {
      "get": {
        "tags": [
          "AISP"
        ],
        "summary": "Get account balances",
        "operationId": "aispBalances",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "accountId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-consent-id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Authorised AISP consent ID. Required for all account information endpoints."
          },
          {
            "$ref": "#/components/parameters/XFapiInteractionId"
          },
          {
            "$ref": "#/components/parameters/XFapiCustomerIpAddress"
          },
          {
            "$ref": "#/components/parameters/XFapiAuthDate"
          },
          {
            "$ref": "#/components/parameters/LimitParam"
          },
          {
            "$ref": "#/components/parameters/CursorParam"
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            },
            "description": "Page offset (additive — omitting preserves legacy behaviour)."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Account balances",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/Balance"
                          }
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Account balance snapshot",
                    "value": {
                      "data": [
                        {
                          "balance_type": "ClosingAvailable",
                          "amount": "1500000",
                          "currency": "XAF",
                          "credit_debit_indicator": "Credit",
                          "date_time": "2026-05-02T10:15:30Z"
                        }
                      ],
                      "pagination": {
                        "page": 1,
                        "limit": 20,
                        "total": 150,
                        "has_next": true
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Get account balances.\n\n**Tag:** AISP\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/aisp/accounts/{accountId}/balances\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/aisp/accounts/{accountId}/balances',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/aisp/accounts/{accountId}/balances\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/aisp/accounts/{accountId}/balances',\n]);\n\nprint_r($response->data);"
          }
        ],
        "x-pagination-style": "cursor"
      }
    },
    "/v1/aisp/accounts/{accountId}/transactions": {
      "get": {
        "tags": [
          "AISP"
        ],
        "summary": "List transactions",
        "operationId": "aispTransactions",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "accountId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-consent-id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Authorised AISP consent ID. Required for all account information endpoints."
          },
          {
            "name": "from_date",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "to_date",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 25,
              "maximum": 100
            },
            "description": "Items per page"
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 0
            },
            "description": "Items to skip Legacy: kept for backwards compatibility — prefer starting_after/ending_before (see x-pagination)."
          },
          {
            "name": "sort_by",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "created_at"
            },
            "description": "Sort field"
          },
          {
            "name": "sort_order",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "asc",
                "desc"
              ],
              "default": "desc"
            },
            "description": "Sort direction"
          },
          {
            "$ref": "#/components/parameters/XFapiInteractionId"
          },
          {
            "$ref": "#/components/parameters/XFapiCustomerIpAddress"
          },
          {
            "$ref": "#/components/parameters/XFapiAuthDate"
          },
          {
            "name": "starting_after",
            "in": "query",
            "required": false,
            "description": "Cursor pagination — returns the page of results AFTER this resource id. Mutually exclusive with offset/ending_before. Preferred for new integrations (see x-pagination).",
            "schema": {
              "type": "string",
              "example": "acc_01HZQ..."
            }
          },
          {
            "name": "ending_before",
            "in": "query",
            "required": false,
            "description": "Cursor pagination — returns the page of results BEFORE this resource id. Mutually exclusive with offset/starting_after.",
            "schema": {
              "type": "string",
              "example": "acc_01HZQ..."
            }
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Transactions list",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/Transaction"
                          }
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Cursor-paginated list",
                    "value": {
                      "data": [
                        {
                          "transaction_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "amount": "25000",
                          "currency": "XAF",
                          "type": "debit",
                          "timestamp": "2026-05-02T10:15:30Z",
                          "id": "obj_01HZX9TRJ4M7YQK6P3W2VBDN5K",
                          "object": "resource",
                          "created_at": "2026-05-02T10:15:30Z"
                        },
                        {
                          "transaction_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "amount": "25000",
                          "currency": "XAF",
                          "type": "debit",
                          "timestamp": "2026-05-02T10:15:30Z",
                          "id": "obj_01HZX9TRJ4M7YQK6P3W2VBDN5L",
                          "object": "resource",
                          "created_at": "2026-05-02T10:15:31Z"
                        }
                      ],
                      "pagination": {
                        "page": 1,
                        "limit": 20,
                        "total": 150,
                        "has_next": true,
                        "has_more": true,
                        "next_cursor": "cursor_01HZX9TRJ4M7YQK6P3W2VBDN5M",
                        "prev_cursor": null,
                        "total_count": 247
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Pagination-Mode": {
                "description": "Either `cursor` or `offset` — echoes which mode the gateway interpreted.",
                "schema": {
                  "type": "string",
                  "enum": [
                    "cursor",
                    "offset"
                  ]
                }
              },
              "X-Pagination-Has-More": {
                "description": "Boolean (`true`/`false`) — whether more results are available.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Pagination-Next-Cursor": {
                "description": "Resource id to pass as `starting_after` for the next page (cursor mode only).",
                "schema": {
                  "type": "string"
                }
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "List transactions.\n\n**Tag:** AISP\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/aisp/accounts/{accountId}/transactions\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/aisp/accounts/{accountId}/transactions',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/aisp/accounts/{accountId}/transactions\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/aisp/accounts/{accountId}/transactions',\n]);\n\nprint_r($response->data);"
          }
        ],
        "x-pagination-style": "cursor"
      }
    },
    "/v1/aisp/accounts/{accountId}/beneficiaries": {
      "get": {
        "tags": [
          "AISP"
        ],
        "summary": "List beneficiaries",
        "operationId": "aispBeneficiaries",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "accountId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-consent-id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Authorised AISP consent ID. Required for all account information endpoints."
          },
          {
            "$ref": "#/components/parameters/LimitParam"
          },
          {
            "$ref": "#/components/parameters/CursorParam"
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            },
            "description": "Page offset (additive — omitting preserves legacy behaviour)."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Beneficiaries list",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/GatewayBeneficiary"
                          }
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Cursor-paginated list",
                    "value": {
                      "data": [
                        {
                          "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "merchant_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "name": "name_value",
                          "channel": "mobile_money",
                          "object": "resource",
                          "created_at": "2026-05-02T10:15:30Z"
                        },
                        {
                          "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "merchant_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "name": "name_value",
                          "channel": "mobile_money",
                          "object": "resource",
                          "created_at": "2026-05-02T10:15:31Z"
                        }
                      ],
                      "pagination": {
                        "page": 1,
                        "limit": 20,
                        "total": 150,
                        "has_next": true,
                        "has_more": true,
                        "next_cursor": "cursor_01HZX9TRJ4M7YQK6P3W2VBDN5M",
                        "prev_cursor": null,
                        "total_count": 247
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "List beneficiaries.\n\n**Tag:** AISP\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/aisp/accounts/{accountId}/beneficiaries\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/aisp/accounts/{accountId}/beneficiaries',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/aisp/accounts/{accountId}/beneficiaries\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/aisp/accounts/{accountId}/beneficiaries',\n]);\n\nprint_r($response->data);"
          }
        ],
        "x-pagination-style": "cursor"
      }
    },
    "/v1/aisp/accounts/{accountId}/standing-orders": {
      "get": {
        "tags": [
          "AISP"
        ],
        "summary": "List standing orders",
        "operationId": "aispStandingOrders",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "accountId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-consent-id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Authorised AISP consent ID. Required for all account information endpoints."
          },
          {
            "$ref": "#/components/parameters/LimitParam"
          },
          {
            "$ref": "#/components/parameters/CursorParam"
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            },
            "description": "Page offset (additive — omitting preserves legacy behaviour)."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Standing orders list",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {}
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Cursor-paginated list",
                    "value": {
                      "data": [
                        "data_value",
                        "data_value"
                      ],
                      "pagination": {
                        "page": 1,
                        "limit": 20,
                        "total": 150,
                        "has_next": true,
                        "has_more": true,
                        "next_cursor": "cursor_01HZX9TRJ4M7YQK6P3W2VBDN5M",
                        "prev_cursor": null,
                        "total_count": 247
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "List standing orders.\n\n**Tag:** AISP\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/aisp/accounts/{accountId}/standing-orders\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/aisp/accounts/{accountId}/standing-orders',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/aisp/accounts/{accountId}/standing-orders\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/aisp/accounts/{accountId}/standing-orders',\n]);\n\nprint_r($response->data);"
          }
        ],
        "x-pagination-style": "cursor"
      }
    },
    "/v1/aisp/accounts/{accountId}/direct-debits": {
      "get": {
        "tags": [
          "AISP"
        ],
        "summary": "List direct debits",
        "operationId": "aispDirectDebits",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "accountId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-consent-id",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Authorised AISP consent ID. Required for all account information endpoints."
          },
          {
            "$ref": "#/components/parameters/LimitParam"
          },
          {
            "$ref": "#/components/parameters/CursorParam"
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            },
            "description": "Page offset (additive — omitting preserves legacy behaviour)."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Direct debits list",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {}
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Cursor-paginated list",
                    "value": {
                      "data": [
                        "data_value",
                        "data_value"
                      ],
                      "pagination": {
                        "page": 1,
                        "limit": 20,
                        "total": 150,
                        "has_next": true,
                        "has_more": true,
                        "next_cursor": "cursor_01HZX9TRJ4M7YQK6P3W2VBDN5M",
                        "prev_cursor": null,
                        "total_count": 247
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "List direct debits.\n\n**Tag:** AISP\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/aisp/accounts/{accountId}/direct-debits\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/aisp/accounts/{accountId}/direct-debits',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/aisp/accounts/{accountId}/direct-debits\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/aisp/accounts/{accountId}/direct-debits',\n]);\n\nprint_r($response->data);"
          }
        ],
        "x-pagination-style": "cursor"
      }
    },
    "/v1/pisp/consents": {
      "post": {
        "tags": [
          "PISP"
        ],
        "summary": "Create payment consent",
        "operationId": "pispCreateConsent",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/XFapiInteractionId"
          },
          {
            "$ref": "#/components/parameters/XFapiCustomerIpAddress"
          },
          {
            "$ref": "#/components/parameters/XFapiAuthDate"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "amount",
                  "currency",
                  "creditor_account"
                ],
                "properties": {
                  "amount": {
                    "type": "string",
                    "example": "50000",
                    "pattern": "^[0-9]{1,15}$",
                    "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits). Must be consistent with the currency field."
                  },
                  "currency": {
                    "type": "string",
                    "example": "XAF",
                    "enum": [
                      "XAF",
                      "XOF",
                      "USD",
                      "EUR",
                      "GBP",
                      "CNY",
                      "NGN",
                      "GHS",
                      "KES",
                      "ZAR"
                    ],
                    "default": "XAF",
                    "description": "ISO 4217 currency code. Default is XAF (Central African CFA Franc)."
                  },
                  "debtor_account": {
                    "type": "string"
                  },
                  "creditor_account": {
                    "type": "string"
                  },
                  "reference": {
                    "type": "string",
                    "example": "Invoice-2026-001"
                  }
                }
              },
              "example": {
                "amount": "50000",
                "currency": "XAF",
                "creditor_account": "CM21 10003 00200 9876543210 045",
                "reference": "Invoice-2026-001"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Payment consent created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Consent"
                },
                "examples": {
                  "default": {
                    "summary": "Successful response envelope",
                    "value": {
                      "consent_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                      "status": "AwaitingAuthorisation",
                      "permissions": [
                        "permissions_value"
                      ],
                      "expiration_date": "2026-05-02T10:15:30Z",
                      "created_at": "2026-05-02T10:15:30Z",
                      "success": true,
                      "data": {
                        "id": "obj_01HZX9TRJ4M7YQK6P3W2VBDN5K",
                        "object": "resource",
                        "created_at": "2026-05-02T10:15:30Z"
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      }
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Create payment consent.\n\n**Tag:** PISP\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/pisp/consents\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/pisp/consents',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/pisp/consents\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/pisp/consents',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/pisp/domestic-payment": {
      "post": {
        "tags": [
          "PISP"
        ],
        "summary": "Submit domestic payment",
        "operationId": "pispDomesticPayment",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/XFapiInteractionId"
          },
          {
            "$ref": "#/components/parameters/XFapiCustomerIpAddress"
          },
          {
            "$ref": "#/components/parameters/XFapiAuthDate"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "consent_id",
                  "amount",
                  "currency",
                  "debtor_account",
                  "creditor_account",
                  "reference"
                ],
                "properties": {
                  "consent_id": {
                    "type": "string"
                  },
                  "amount": {
                    "type": "string",
                    "example": "50000",
                    "pattern": "^[0-9]{1,15}$",
                    "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits). Must be consistent with the currency field."
                  },
                  "currency": {
                    "type": "string",
                    "example": "XAF",
                    "enum": [
                      "XAF",
                      "XOF",
                      "USD",
                      "EUR",
                      "GBP",
                      "CNY",
                      "NGN",
                      "GHS",
                      "KES",
                      "ZAR"
                    ],
                    "default": "XAF",
                    "description": "ISO 4217 currency code. Default is XAF (Central African CFA Franc)."
                  },
                  "debtor_account": {
                    "type": "string"
                  },
                  "creditor_account": {
                    "type": "string"
                  },
                  "reference": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Payment submitted",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/StandardResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/Payment"
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Payment intent created",
                    "value": {
                      "data": {
                        "payment_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                        "amount": "5000",
                        "currency": "XAF",
                        "status": "pending",
                        "debtor_account": "CM21 10003 00100 0123456789 023",
                        "creditor_account": "CM21 10003 00200 9876543210 045",
                        "id": "pi_01HZX9TRJ4M7YQK6P3W2VBDN5K",
                        "object": "payment_intent",
                        "client_secret": "pi_01HZX9TRJ4M7YQK6P3W2VBDN5K_secret_aBc123",
                        "payment_method_types": [
                          "mobile_money",
                          "card",
                          "bank_transfer"
                        ],
                        "idempotency_key": "550e8400-e29b-41d4-a716-446655440000",
                        "created_at": "2026-05-02T10:15:30Z"
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": " Responses will conform to the StandardResponse envelope in a future minor release.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/pisp/domestic-payment\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/pisp/domestic-payment',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/pisp/domestic-payment\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/pisp/domestic-payment',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/pisp/payment-submission": {
      "post": {
        "tags": [
          "PISP"
        ],
        "summary": "Confirm payment submission",
        "operationId": "pispPaymentSubmission",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/XFapiInteractionId"
          },
          {
            "$ref": "#/components/parameters/XFapiCustomerIpAddress"
          },
          {
            "$ref": "#/components/parameters/XFapiAuthDate"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "payment_id",
                  "consent_id",
                  "amount",
                  "currency",
                  "debtor_account",
                  "creditor_account"
                ],
                "properties": {
                  "payment_id": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 128
                  },
                  "consent_id": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 128
                  },
                  "amount": {
                    "type": "string",
                    "pattern": "^[0-9]{1,15}$",
                    "example": "50000"
                  },
                  "currency": {
                    "type": "string",
                    "enum": [
                      "XAF",
                      "XOF",
                      "EUR",
                      "USD"
                    ],
                    "example": "XAF"
                  },
                  "debtor_account": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 64,
                    "example": "10005-00001-09876543210-45"
                  },
                  "creditor_account": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 64,
                    "example": "10005-00001-12345678901-23"
                  }
                }
              },
              "example": {
                "payment_id": "pmt_01HFG",
                "consent_id": "cns_01HFG",
                "amount": "50000",
                "currency": "XAF",
                "debtor_account": "10005-00001-09876543210-45",
                "creditor_account": "10005-00001-12345678901-23"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Payment submission confirmed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Payment"
                },
                "examples": {
                  "default": {
                    "summary": "Payment intent created",
                    "value": {
                      "payment_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                      "amount": "50000",
                      "currency": "XAF",
                      "status": "pending",
                      "debtor_account": "CM21 10003 00100 0123456789 023",
                      "creditor_account": "CM21 10003 00200 9876543210 045",
                      "success": true,
                      "data": {
                        "id": "pi_01HZX9TRJ4M7YQK6P3W2VBDN5K",
                        "object": "payment_intent",
                        "amount": "5000",
                        "currency": "XAF",
                        "status": "requires_confirmation",
                        "client_secret": "pi_01HZX9TRJ4M7YQK6P3W2VBDN5K_secret_aBc123",
                        "payment_method_types": [
                          "mobile_money",
                          "card",
                          "bank_transfer"
                        ],
                        "idempotency_key": "550e8400-e29b-41d4-a716-446655440000",
                        "created_at": "2026-05-02T10:15:30Z"
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      }
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Confirm payment submission.\n\n**Tag:** PISP\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/pisp/payment-submission\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/pisp/payment-submission',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/pisp/payment-submission\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/pisp/payment-submission',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/pisp/payments/{paymentId}": {
      "get": {
        "tags": [
          "PISP"
        ],
        "summary": "Get payment details",
        "operationId": "pispPaymentDetails",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "paymentId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Payment details",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/StandardResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/Payment"
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Payment intent created",
                    "value": {
                      "data": {
                        "payment_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                        "amount": "5000",
                        "currency": "XAF",
                        "status": "pending",
                        "debtor_account": "CM21 10003 00100 0123456789 023",
                        "creditor_account": "CM21 10003 00200 9876543210 045",
                        "id": "pi_01HZX9TRJ4M7YQK6P3W2VBDN5K",
                        "object": "payment_intent",
                        "client_secret": "pi_01HZX9TRJ4M7YQK6P3W2VBDN5K_secret_aBc123",
                        "payment_method_types": [
                          "mobile_money",
                          "card",
                          "bank_transfer"
                        ],
                        "idempotency_key": "550e8400-e29b-41d4-a716-446655440000",
                        "created_at": "2026-05-02T10:15:30Z"
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Get payment details.\n\n**Tag:** PISP\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/pisp/payments/{paymentId}\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/pisp/payments/{paymentId}',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/pisp/payments/{paymentId}\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/pisp/payments/{paymentId}',\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/consents/{consentId}/authorize": {
      "post": {
        "tags": [
          "Consent Management"
        ],
        "summary": "Authorize consent",
        "operationId": "consentAuthorize",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "consentId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Consent authorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Consent"
                },
                "examples": {
                  "default": {
                    "summary": "Successful response envelope",
                    "value": {
                      "consent_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                      "status": "AwaitingAuthorisation",
                      "permissions": [
                        "permissions_value"
                      ],
                      "expiration_date": "2026-05-02T10:15:30Z",
                      "created_at": "2026-05-02T10:15:30Z",
                      "success": true,
                      "data": {
                        "id": "obj_01HZX9TRJ4M7YQK6P3W2VBDN5K",
                        "object": "resource",
                        "created_at": "2026-05-02T10:15:30Z"
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      }
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Authorize consent.\n\n**Tag:** Consent Management\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/consents/{consentId}/authorize\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/consents/{consentId}/authorize',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/consents/{consentId}/authorize\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/consents/{consentId}/authorize',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/consents/{consentId}/revoke": {
      "post": {
        "tags": [
          "Consent Management"
        ],
        "summary": "Revoke consent",
        "operationId": "consentRevoke",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "consentId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "reason": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Consent revoked",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Consent"
                },
                "examples": {
                  "default": {
                    "summary": "Successful response envelope",
                    "value": {
                      "consent_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                      "status": "AwaitingAuthorisation",
                      "permissions": [
                        "permissions_value"
                      ],
                      "expiration_date": "2026-05-02T10:15:30Z",
                      "created_at": "2026-05-02T10:15:30Z",
                      "success": true,
                      "data": {
                        "id": "obj_01HZX9TRJ4M7YQK6P3W2VBDN5K",
                        "object": "resource",
                        "created_at": "2026-05-02T10:15:30Z"
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      }
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Revoke consent.\n\n**Tag:** Consent Management\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/consents/{consentId}/revoke\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/consents/{consentId}/revoke',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/consents/{consentId}/revoke\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/consents/{consentId}/revoke',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/consents": {
      "get": {
        "tags": [
          "Consent Management"
        ],
        "summary": "List consents",
        "operationId": "consentsList",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 25,
              "maximum": 100
            },
            "description": "Items per page"
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 0
            },
            "description": "Items to skip Legacy: kept for backwards compatibility — prefer starting_after/ending_before (see x-pagination)."
          },
          {
            "name": "sort_by",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "created_at"
            },
            "description": "Sort field"
          },
          {
            "name": "sort_order",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "asc",
                "desc"
              ],
              "default": "desc"
            },
            "description": "Sort direction"
          },
          {
            "name": "starting_after",
            "in": "query",
            "required": false,
            "description": "Cursor pagination — returns the page of results AFTER this resource id. Mutually exclusive with offset/ending_before. Preferred for new integrations (see x-pagination).",
            "schema": {
              "type": "string",
              "example": "acc_01HZQ..."
            }
          },
          {
            "name": "ending_before",
            "in": "query",
            "required": false,
            "description": "Cursor pagination — returns the page of results BEFORE this resource id. Mutually exclusive with offset/starting_after.",
            "schema": {
              "type": "string",
              "example": "acc_01HZQ..."
            }
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Consents list",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/Consent"
                          }
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Cursor-paginated list",
                    "value": {
                      "data": [
                        {
                          "consent_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "status": "AwaitingAuthorisation",
                          "permissions": [
                            "permissions_value"
                          ],
                          "expiration_date": "2026-05-02T10:15:30Z",
                          "created_at": "2026-05-02T10:15:30Z",
                          "id": "obj_01HZX9TRJ4M7YQK6P3W2VBDN5K",
                          "object": "resource"
                        },
                        {
                          "consent_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "status": "AwaitingAuthorisation",
                          "permissions": [
                            "permissions_value"
                          ],
                          "expiration_date": "2026-05-02T10:15:30Z",
                          "created_at": "2026-05-02T10:15:31Z",
                          "id": "obj_01HZX9TRJ4M7YQK6P3W2VBDN5L",
                          "object": "resource"
                        }
                      ],
                      "pagination": {
                        "page": 1,
                        "limit": 20,
                        "total": 150,
                        "has_next": true,
                        "has_more": true,
                        "next_cursor": "cursor_01HZX9TRJ4M7YQK6P3W2VBDN5M",
                        "prev_cursor": null,
                        "total_count": 247
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Pagination-Mode": {
                "description": "Either `cursor` or `offset` — echoes which mode the gateway interpreted.",
                "schema": {
                  "type": "string",
                  "enum": [
                    "cursor",
                    "offset"
                  ]
                }
              },
              "X-Pagination-Has-More": {
                "description": "Boolean (`true`/`false`) — whether more results are available.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Pagination-Next-Cursor": {
                "description": "Resource id to pass as `starting_after` for the next page (cursor mode only).",
                "schema": {
                  "type": "string"
                }
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "List consents.\n\n**Tag:** Consent Management\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/consents\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/consents',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/consents\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/consents',\n]);\n\nprint_r($response->data);"
          }
        ]
      },
      "post": {
        "tags": [
          "Consents"
        ],
        "summary": "Create consent",
        "description": "Rail-agnostic consent factory. Routes to `aisp-create-consent`, `pisp-create-consent`, or the CBPII module based on `type`.",
        "operationId": "createConsent",
        "parameters": [
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ConsentCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Consent created in AwaitingAuthorisation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Consent"
                },
                "example": {
                  "consent_id": "string",
                  "status": "AwaitingAuthorisation",
                  "permissions": [
                    "string"
                  ],
                  "expiration_date": "2026-01-01T00:00:00Z",
                  "created_at": "2026-01-01T00:00:00Z"
                }
              }
            },
            "headers": {
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionId"
              }
            }
          },
          "400": {
            "description": "400 Bad Request — the request failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://api.kangopenbanking.com/v1/errors/validation-error",
                  "title": "Validation Error",
                  "status": 400
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://api.kangopenbanking.com/v1/errors/validation-error",
                  "title": "Validation Error",
                  "status": 400
                }
              }
            }
          },
          "401": {
            "description": "401 Unauthorized — credentials are missing, expired or invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://api.kangopenbanking.com/v1/errors/unauthorized",
                  "title": "Unauthorized",
                  "status": 401
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://api.kangopenbanking.com/v1/errors/unauthorized",
                  "title": "Unauthorized",
                  "status": 401
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. Retry after the interval in `Retry-After`.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before retrying."
              },
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "rateLimited": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "500 Internal Server Error — an unexpected condition prevented completion.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://api.kangopenbanking.com/v1/errors/internal-error",
                  "title": "Internal Server Error",
                  "status": 500
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://api.kangopenbanking.com/v1/errors/internal-error",
                  "title": "Internal Server Error",
                  "status": 500
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/consents\" \\\n  -H \"Authorization: Bearer $KOB_ACCESS_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangOpenBanking } from \"@kangopenbanking/sdk\";\n\nconst kob = new KangOpenBanking({ apiKey: process.env.KOB_API_KEY });\nconst res = await kob.request(\"POST\", \"/v1/consents\", { /* payload */ });\nconsole.log(res);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import KangOpenBanking\n\nkob = KangOpenBanking(api_key=os.environ[\"KOB_API_KEY\"])\nres = kob.request(\"POST\", \"/v1/consents\", json={})\nprint(res)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\n$kob = new KangOpenBanking\\KangOpenBanking(getenv('KOB_API_KEY'));\n$res = $kob->request('POST', '/v1/consents', []);\nprint_r($res);"
          }
        ]
      }
    },
    "/v1/credit/score": {
      "get": {
        "tags": [
          "Credit Scoring"
        ],
        "summary": "Get credit score",
        "operationId": "creditScoreFetch",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Credit score",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/StandardResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/CreditScore"
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Successful response envelope",
                    "value": {
                      "data": {
                        "score": 680,
                        "grade": "A",
                        "calculated_at": "2026-05-02T10:15:30Z",
                        "id": "obj_01HZX9TRJ4M7YQK6P3W2VBDN5K",
                        "object": "resource",
                        "created_at": "2026-05-02T10:15:30Z"
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Get credit score.\n\n**Tag:** Credit Scoring\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/credit/score\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/credit/score',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/credit/score\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/credit/score',\n]);\n\nprint_r($response->data);"
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ]
      },
      "post": {
        "tags": [
          "Credit Scoring"
        ],
        "summary": "Calculate credit score",
        "operationId": "creditScoreCalculate",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Score calculated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreditScore"
                },
                "examples": {
                  "default": {
                    "summary": "Successful response envelope",
                    "value": {
                      "score": 680,
                      "grade": "A",
                      "calculated_at": "2026-05-02T10:15:30Z",
                      "success": true,
                      "data": {
                        "id": "obj_01HZX9TRJ4M7YQK6P3W2VBDN5K",
                        "object": "resource",
                        "created_at": "2026-05-02T10:15:30Z"
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      }
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "description": "Calculate credit score.\n\n**Tag:** Credit Scoring\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/credit/score\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/credit/score',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/credit/score\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/credit/score',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/credit/simulate": {
      "post": {
        "tags": [
          "Credit Scoring"
        ],
        "summary": "Simulate score impact",
        "operationId": "creditScoreSimulate",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "action_type": {
                    "type": "string",
                    "enum": [
                      "pay_off_debt",
                      "new_credit",
                      "late_payment"
                    ]
                  },
                  "amount": {
                    "type": "string",
                    "example": "100000",
                    "pattern": "^[0-9]{1,15}$",
                    "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits)."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Simulation result",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "current_score": {
                      "type": "integer"
                    },
                    "simulated_score": {
                      "type": "integer"
                    },
                    "impact": {
                      "type": "integer"
                    },
                    "grade_change": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "description": "Simulate score impact.\n\n**Tag:** Credit Scoring\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/credit/simulate\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/credit/simulate',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/credit/simulate\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/credit/simulate',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/credit/tips": {
      "get": {
        "tags": [
          "Credit Scoring"
        ],
        "summary": "Get improvement tips",
        "operationId": "creditScoreTips",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Tips list",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {}
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Cursor-paginated list",
                    "value": {
                      "data": [
                        "data_value",
                        "data_value"
                      ],
                      "pagination": {
                        "page": 1,
                        "limit": 20,
                        "total": 150,
                        "has_next": true,
                        "has_more": true,
                        "next_cursor": "cursor_01HZX9TRJ4M7YQK6P3W2VBDN5M",
                        "prev_cursor": null,
                        "total_count": 247
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/LimitParam"
          },
          {
            "$ref": "#/components/parameters/CursorParam"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "description": "Get improvement tips.\n\n**Tag:** Credit Scoring\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/credit/tips\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/credit/tips',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/credit/tips\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/credit/tips',\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/credit/report": {
      "post": {
        "tags": [
          "Credit Scoring"
        ],
        "summary": "Generate credit report",
        "operationId": "creditReportGenerate",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Report generated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "report_id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "score": {
                      "$ref": "#/components/schemas/CreditScore"
                    },
                    "generated_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "description": "Generate credit report.\n\n**Tag:** Credit Scoring\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/credit/report\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/credit/report',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/credit/report\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/credit/report',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/loans/products": {
      "get": {
        "tags": [
          "Loans"
        ],
        "summary": "List loan products",
        "operationId": "loanProducts",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Loan products",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {}
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Cursor-paginated list",
                    "value": {
                      "data": [
                        "data_value",
                        "data_value"
                      ],
                      "pagination": {
                        "page": 1,
                        "limit": 20,
                        "total": 150,
                        "has_next": true,
                        "has_more": true,
                        "next_cursor": "cursor_01HZX9TRJ4M7YQK6P3W2VBDN5M",
                        "prev_cursor": null,
                        "total_count": 247
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/PageParam"
          },
          {
            "$ref": "#/components/parameters/LimitParam"
          },
          {
            "$ref": "#/components/parameters/CursorParam"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "description": "List loan products.\n\n**Tag:** Loans\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/loans/products\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/loans/products',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/loans/products\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/loans/products',\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/loans/apply": {
      "post": {
        "tags": [
          "Loans"
        ],
        "summary": "Apply for loan",
        "operationId": "loanApply",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "product_id",
                  "amount",
                  "term_months"
                ],
                "properties": {
                  "product_id": {
                    "type": "string"
                  },
                  "amount": {
                    "type": "string",
                    "example": "1000000",
                    "pattern": "^[0-9]{1,15}$",
                    "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits)."
                  },
                  "term_months": {
                    "type": "integer",
                    "example": 12
                  },
                  "purpose": {
                    "type": "string",
                    "example": "Business expansion"
                  }
                }
              },
              "example": {
                "product_id": "prod_abc123",
                "amount": "1000000",
                "term_months": 12,
                "purpose": "Business expansion"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Loan application submitted",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/StandardResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/LoanApplication"
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Successful response envelope",
                    "value": {
                      "data": {
                        "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                        "product_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                        "amount": "1000000",
                        "currency": "XAF",
                        "term_months": 12,
                        "status": "applied",
                        "object": "resource",
                        "created_at": "2026-05-02T10:15:30Z"
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": " Responses will conform to the StandardResponse envelope in a future minor release.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/loans/apply\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/loans/apply',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/loans/apply\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/loans/apply',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/loans/calculate": {
      "post": {
        "tags": [
          "Loans"
        ],
        "summary": "Calculate loan terms",
        "operationId": "loanCalculate",
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "amount",
                  "term_months",
                  "interest_rate"
                ],
                "properties": {
                  "amount": {
                    "type": "string",
                    "example": "1000000",
                    "pattern": "^[0-9]{1,15}$",
                    "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits)."
                  },
                  "term_months": {
                    "type": "integer",
                    "example": 12
                  },
                  "interest_rate": {
                    "type": "number",
                    "example": 15
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Loan calculation",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "monthly_payment": {
                      "type": "number",
                      "example": 92500
                    },
                    "total_interest": {
                      "type": "number",
                      "example": 110000,
                      "deprecated": true,
                      "x-successor": "total_interest_money",
                      "x-sunset": "5.0.0",
                      "description": "Deprecated: floating-point monetary value (IEEE-754 binary64 cannot represent decimal minor units exactly). Use `total_interest_money` instead. Removal is scheduled for v5.0.0."
                    },
                    "total_repayment": {
                      "type": "number",
                      "example": 1110000,
                      "deprecated": true,
                      "x-successor": "total_repayment_money",
                      "x-sunset": "5.0.0",
                      "description": "Deprecated: floating-point monetary value (IEEE-754 binary64 cannot represent decimal minor units exactly). Use `total_repayment_money` instead. Removal is scheduled for v5.0.0."
                    },
                    "total_interest_money": {
                      "$ref": "#/components/schemas/Money",
                      "description": "Canonical string-encoded successor to `total_interest`. Amount and ISO 4217 currency travel together (ISO 20022 ActiveCurrencyAndAmount). Prefer this field: it is exact for zero-decimal currencies (XAF, XOF) and immune to IEEE-754 drift.",
                      "x-added-in": "4.54.0"
                    },
                    "total_repayment_money": {
                      "$ref": "#/components/schemas/Money",
                      "description": "Canonical string-encoded successor to `total_repayment`. Amount and ISO 4217 currency travel together (ISO 20022 ActiveCurrencyAndAmount). Prefer this field: it is exact for zero-decimal currencies (XAF, XOF) and immune to IEEE-754 drift.",
                      "x-added-in": "4.54.0"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "description": "Calculate loan terms.\n\n**Tag:** Loans\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/loans/calculate\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/loans/calculate',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/loans/calculate\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/loans/calculate',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/loans/{loanId}/approve": {
      "post": {
        "tags": [
          "Loans"
        ],
        "summary": "Approve loan application",
        "operationId": "loanApprove",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "loanId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "approved_amount": {
                    "type": "number",
                    "deprecated": true,
                    "x-successor": "approved_amount_money",
                    "x-sunset": "5.0.0",
                    "description": "Deprecated: floating-point monetary value (IEEE-754 binary64 cannot represent decimal minor units exactly). Use `approved_amount_money` instead. Removal is scheduled for v5.0.0."
                  },
                  "approved_rate": {
                    "type": "number"
                  },
                  "conditions": {
                    "type": "string"
                  },
                  "approved_amount_money": {
                    "$ref": "#/components/schemas/Money",
                    "description": "Canonical string-encoded successor to `approved_amount`. Amount and ISO 4217 currency travel together (ISO 20022 ActiveCurrencyAndAmount). Prefer this field: it is exact for zero-decimal currencies (XAF, XOF) and immune to IEEE-754 drift.",
                    "x-added-in": "4.54.0"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Loan approved",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LoanApplication"
                },
                "examples": {
                  "default": {
                    "summary": "Successful response envelope",
                    "value": {
                      "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                      "product_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                      "amount": "1000000",
                      "currency": "XAF",
                      "term_months": 12,
                      "status": "applied",
                      "success": true,
                      "data": {
                        "id": "obj_01HZX9TRJ4M7YQK6P3W2VBDN5K",
                        "object": "resource",
                        "created_at": "2026-05-02T10:15:30Z"
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      }
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Approve loan application.\n\n**Tag:** Loans\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/loans/{loanId}/approve\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/loans/{loanId}/approve',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/loans/{loanId}/approve\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/loans/{loanId}/approve',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/loans/{loanId}/disburse": {
      "post": {
        "tags": [
          "Loans"
        ],
        "summary": "Disburse loan",
        "operationId": "loanDisburse",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "loanId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "disbursement_account": {
                    "type": "string"
                  },
                  "disbursement_method": {
                    "type": "string",
                    "enum": [
                      "bank_transfer",
                      "mobile_money"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Loan disbursed with ledger posting",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LoanApplication"
                },
                "examples": {
                  "default": {
                    "summary": "Successful response envelope",
                    "value": {
                      "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                      "product_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                      "amount": "1000000",
                      "currency": "XAF",
                      "term_months": 12,
                      "status": "applied",
                      "success": true,
                      "data": {
                        "id": "obj_01HZX9TRJ4M7YQK6P3W2VBDN5K",
                        "object": "resource",
                        "created_at": "2026-05-02T10:15:30Z"
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      }
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Disburse loan.\n\n**Tag:** Loans\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/loans/{loanId}/disburse\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/loans/{loanId}/disburse',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/loans/{loanId}/disburse\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/loans/{loanId}/disburse',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/loans/{loanId}/schedule": {
      "get": {
        "tags": [
          "Loans"
        ],
        "summary": "Get repayment schedule",
        "operationId": "loanSchedule",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "loanId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/LimitParam"
          },
          {
            "$ref": "#/components/parameters/CursorParam"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Repayment schedule",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/LoanScheduleItem"
                          }
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Successful response envelope",
                    "value": {
                      "data": [
                        {
                          "installment_number": 1,
                          "due_date": "2026-03-16",
                          "principal_amount": "80000",
                          "interest_amount": "80000",
                          "total_due_amount": "80000"
                        }
                      ],
                      "pagination": {
                        "page": 1,
                        "limit": 20,
                        "total": 150,
                        "has_next": true
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Get repayment schedule.\n\n**Tag:** Loans\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/loans/{loanId}/schedule\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/loans/{loanId}/schedule',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/loans/{loanId}/schedule\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/loans/{loanId}/schedule',\n]);\n\nprint_r($response->data);"
          }
        ]
      },
      "post": {
        "tags": [
          "Loans"
        ],
        "summary": "Generate repayment schedule",
        "operationId": "loanGenerateSchedule",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "loanId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "201": {
            "description": "Schedule generated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Generate repayment schedule.\n\n**Tag:** Loans\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/loans/{loanId}/schedule\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/loans/{loanId}/schedule',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/loans/{loanId}/schedule\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/loans/{loanId}/schedule',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/loans/{loanId}/repay": {
      "post": {
        "tags": [
          "Loans"
        ],
        "summary": "Make loan repayment",
        "operationId": "loanRepay",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "loanId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "amount"
                ],
                "properties": {
                  "amount": {
                    "type": "string",
                    "example": "92500",
                    "pattern": "^[0-9]{1,15}$",
                    "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits)."
                  },
                  "payment_method": {
                    "type": "string",
                    "enum": [
                      "bank_transfer",
                      "mobile_money",
                      "savings_debit"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Repayment recorded with schedule/ledger update",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "repayment_id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "amount_applied": {
                      "type": "number",
                      "deprecated": true,
                      "x-successor": "amount_applied_money",
                      "x-sunset": "5.0.0",
                      "description": "Deprecated: floating-point monetary value (IEEE-754 binary64 cannot represent decimal minor units exactly). Use `amount_applied_money` instead. Removal is scheduled for v5.0.0."
                    },
                    "remaining_balance": {
                      "type": "number",
                      "deprecated": true,
                      "x-successor": "remaining_balance_money",
                      "x-sunset": "5.0.0",
                      "description": "Deprecated: floating-point monetary value (IEEE-754 binary64 cannot represent decimal minor units exactly). Use `remaining_balance_money` instead. Removal is scheduled for v5.0.0."
                    },
                    "next_installment": {
                      "$ref": "#/components/schemas/LoanScheduleItem"
                    },
                    "amount_applied_money": {
                      "$ref": "#/components/schemas/Money",
                      "description": "Canonical string-encoded successor to `amount_applied`. Amount and ISO 4217 currency travel together (ISO 20022 ActiveCurrencyAndAmount). Prefer this field: it is exact for zero-decimal currencies (XAF, XOF) and immune to IEEE-754 drift.",
                      "x-added-in": "4.54.0"
                    },
                    "remaining_balance_money": {
                      "$ref": "#/components/schemas/Money",
                      "description": "Canonical string-encoded successor to `remaining_balance`. Amount and ISO 4217 currency travel together (ISO 20022 ActiveCurrencyAndAmount). Prefer this field: it is exact for zero-decimal currencies (XAF, XOF) and immune to IEEE-754 drift.",
                      "x-added-in": "4.54.0"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Make loan repayment.\n\n**Tag:** Loans\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/loans/{loanId}/repay\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/loans/{loanId}/repay',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/loans/{loanId}/repay\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/loans/{loanId}/repay',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/savings/products": {
      "get": {
        "tags": [
          "Savings"
        ],
        "summary": "List savings products",
        "operationId": "savingsProducts",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Savings products",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {}
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Cursor-paginated list",
                    "value": {
                      "data": [
                        "data_value",
                        "data_value"
                      ],
                      "pagination": {
                        "page": 1,
                        "limit": 20,
                        "total": 150,
                        "has_next": true,
                        "has_more": true,
                        "next_cursor": "cursor_01HZX9TRJ4M7YQK6P3W2VBDN5M",
                        "prev_cursor": null,
                        "total_count": 247
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/PageParam"
          },
          {
            "$ref": "#/components/parameters/LimitParam"
          },
          {
            "$ref": "#/components/parameters/CursorParam"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "description": "List savings products.\n\n**Tag:** Savings\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/savings/products\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/savings/products',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/savings/products\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/savings/products',\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/savings/accounts": {
      "post": {
        "tags": [
          "Savings"
        ],
        "summary": "Create savings account",
        "operationId": "savingsCreate",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "product_id"
                ],
                "properties": {
                  "product_id": {
                    "type": "string"
                  },
                  "initial_deposit": {
                    "type": "number",
                    "example": 50000
                  },
                  "currency": {
                    "type": "string",
                    "example": "XAF",
                    "enum": [
                      "XAF",
                      "XOF",
                      "USD",
                      "EUR",
                      "GBP",
                      "CNY",
                      "NGN",
                      "GHS",
                      "KES",
                      "ZAR"
                    ],
                    "default": "XAF",
                    "description": "ISO 4217 currency code. Default is XAF (Central African CFA Franc)."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Savings account created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SavingsAccount"
                },
                "examples": {
                  "default": {
                    "summary": "Successful response envelope",
                    "value": {
                      "account_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                      "balance": "5000",
                      "currency": "XAF",
                      "status": "active",
                      "success": true,
                      "data": {
                        "id": "obj_01HZX9TRJ4M7YQK6P3W2VBDN5K",
                        "object": "resource",
                        "created_at": "2026-05-02T10:15:30Z"
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      }
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Create savings account.\n\n**Tag:** Savings\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/savings/accounts\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/savings/accounts',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/savings/accounts\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/savings/accounts',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      },
      "get": {
        "operationId": "listSavingsAccounts",
        "summary": "List savings accounts",
        "description": "Retrieve a paginated list of savings accounts for the authenticated user. Requires a valid AISP consent.",
        "tags": [
          "Savings",
          "AISP"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "x-consent-id",
            "in": "header",
            "required": true,
            "description": "Active AISP consent ID",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "$ref": "#/components/parameters/PageParam"
          },
          {
            "$ref": "#/components/parameters/LimitParam"
          },
          {
            "$ref": "#/components/parameters/CursorParam"
          },
          {
            "$ref": "#/components/parameters/XFapiInteractionId"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated list of savings accounts",
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/SavingsAccount"
                          }
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Cursor-paginated list",
                    "value": {
                      "data": [
                        {
                          "account_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "balance": "5000",
                          "currency": "XAF",
                          "status": "active",
                          "id": "obj_01HZX9TRJ4M7YQK6P3W2VBDN5K",
                          "object": "resource",
                          "created_at": "2026-05-02T10:15:30Z"
                        },
                        {
                          "account_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "balance": "5000",
                          "currency": "XAF",
                          "status": "active",
                          "id": "obj_01HZX9TRJ4M7YQK6P3W2VBDN5L",
                          "object": "resource",
                          "created_at": "2026-05-02T10:15:31Z"
                        }
                      ],
                      "pagination": {
                        "page": 1,
                        "limit": 20,
                        "total": 150,
                        "has_next": true,
                        "has_more": true,
                        "next_cursor": "cursor_01HZX9TRJ4M7YQK6P3W2VBDN5M",
                        "prev_cursor": null,
                        "total_count": 247
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request — validation failed or malformed input.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          },
          "401": {
            "description": "Unauthorised",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden — consent does not include savings accounts",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests — rate limit exceeded.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/savings/accounts\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/savings/accounts',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/savings/accounts\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/savings/accounts',\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/savings/accounts/{accountId}/deposit": {
      "post": {
        "tags": [
          "Savings"
        ],
        "summary": "Deposit to savings",
        "operationId": "savingsDeposit",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "accountId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "amount"
                ],
                "properties": {
                  "amount": {
                    "type": "string",
                    "example": "50000",
                    "pattern": "^[0-9]{1,15}$",
                    "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits)."
                  },
                  "source": {
                    "type": "string",
                    "enum": [
                      "bank_transfer",
                      "mobile_money"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Deposit recorded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Deposit to savings.\n\n**Tag:** Savings\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/savings/accounts/{accountId}/deposit\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/savings/accounts/{accountId}/deposit',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/savings/accounts/{accountId}/deposit\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/savings/accounts/{accountId}/deposit',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/savings/accounts/{accountId}/withdraw": {
      "post": {
        "tags": [
          "Savings"
        ],
        "summary": "Withdraw from savings",
        "operationId": "savingsWithdraw",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "accountId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "amount"
                ],
                "properties": {
                  "amount": {
                    "type": "string",
                    "example": "25000",
                    "pattern": "^[0-9]{1,15}$",
                    "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits)."
                  },
                  "destination": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Withdrawal recorded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Withdraw from savings.\n\n**Tag:** Savings\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/savings/accounts/{accountId}/withdraw\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/savings/accounts/{accountId}/withdraw',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/savings/accounts/{accountId}/withdraw\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/savings/accounts/{accountId}/withdraw',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/savings/accrue-interest": {
      "post": {
        "tags": [
          "Savings"
        ],
        "summary": "Accrue interest (cron)",
        "description": "Trigger interest accrual across all eligible savings accounts. Designed for scheduled (cron) invocation.",
        "operationId": "savingsAccrueInterest",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "accrual_date": {
                    "type": "string",
                    "format": "date"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Interest accrued",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "accounts_processed": {
                      "type": "integer"
                    },
                    "total_interest": {
                      "type": "number",
                      "deprecated": true,
                      "x-successor": "total_interest_money",
                      "x-sunset": "5.0.0",
                      "description": "Deprecated: floating-point monetary value (IEEE-754 binary64 cannot represent decimal minor units exactly). Use `total_interest_money` instead. Removal is scheduled for v5.0.0."
                    },
                    "accrual_date": {
                      "type": "string",
                      "format": "date"
                    },
                    "total_interest_money": {
                      "$ref": "#/components/schemas/Money",
                      "description": "Canonical string-encoded successor to `total_interest`. Amount and ISO 4217 currency travel together (ISO 20022 ActiveCurrencyAndAmount). Prefer this field: it is exact for zero-decimal currencies (XAF, XOF) and immune to IEEE-754 drift.",
                      "x-added-in": "4.54.0"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/savings/accrue-interest\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/savings/accrue-interest',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/savings/accrue-interest\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/savings/accrue-interest',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/ledger/accounts": {
      "get": {
        "tags": [
          "Ledger"
        ],
        "summary": "List ledger accounts",
        "operationId": "ledgerAccounts",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 25,
              "maximum": 100
            },
            "description": "Items per page"
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 0
            },
            "description": "Items to skip"
          },
          {
            "name": "sort_by",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "created_at"
            },
            "description": "Sort field"
          },
          {
            "name": "sort_order",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "asc",
                "desc"
              ],
              "default": "desc"
            },
            "description": "Sort direction"
          },
          {
            "$ref": "#/components/parameters/StartingAfter"
          },
          {
            "$ref": "#/components/parameters/EndingBefore"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Ledger accounts (chart of accounts)",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/LedgerAccount"
                          }
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Cursor-paginated list",
                    "value": {
                      "data": [
                        {
                          "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "code": "1000",
                          "name": "Cash and Cash Equivalents",
                          "account_type": "asset",
                          "currency": "XAF",
                          "object": "resource",
                          "created_at": "2026-05-02T10:15:30Z"
                        },
                        {
                          "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "code": "1000",
                          "name": "Cash and Cash Equivalents",
                          "account_type": "asset",
                          "currency": "XAF",
                          "object": "resource",
                          "created_at": "2026-05-02T10:15:31Z"
                        }
                      ],
                      "pagination": {
                        "page": 1,
                        "limit": 20,
                        "total": 150,
                        "has_next": true,
                        "has_more": true,
                        "next_cursor": "cursor_01HZX9TRJ4M7YQK6P3W2VBDN5M",
                        "prev_cursor": null,
                        "total_count": 247
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "List ledger accounts.\n\n**Tag:** Ledger\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/ledger/accounts\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/ledger/accounts',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/ledger/accounts\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/ledger/accounts',\n]);\n\nprint_r($response->data);"
          }
        ]
      },
      "post": {
        "tags": [
          "Ledger"
        ],
        "summary": "Create ledger account",
        "operationId": "ledgerAccountCreate",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "code",
                  "name",
                  "account_type"
                ],
                "properties": {
                  "code": {
                    "type": "string",
                    "example": "1000"
                  },
                  "name": {
                    "type": "string",
                    "example": "Cash and Cash Equivalents"
                  },
                  "account_type": {
                    "type": "string",
                    "enum": [
                      "asset",
                      "liability",
                      "equity",
                      "revenue",
                      "expense"
                    ]
                  },
                  "currency": {
                    "type": "string",
                    "example": "XAF",
                    "enum": [
                      "XAF",
                      "XOF",
                      "USD",
                      "EUR",
                      "GBP",
                      "CNY",
                      "NGN",
                      "GHS",
                      "KES",
                      "ZAR"
                    ],
                    "default": "XAF",
                    "description": "ISO 4217 currency code. Default is XAF (Central African CFA Franc)."
                  },
                  "parent_id": {
                    "type": "string",
                    "format": "uuid"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Ledger account created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LedgerAccount"
                },
                "examples": {
                  "default": {
                    "summary": "Successful response envelope",
                    "value": {
                      "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                      "code": "1000",
                      "name": "Cash and Cash Equivalents",
                      "account_type": "asset",
                      "currency": "XAF",
                      "success": true,
                      "data": {
                        "id": "obj_01HZX9TRJ4M7YQK6P3W2VBDN5K",
                        "object": "resource",
                        "created_at": "2026-05-02T10:15:30Z"
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      }
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Create ledger account.\n\n**Tag:** Ledger\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/ledger/accounts\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/ledger/accounts',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/ledger/accounts\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/ledger/accounts',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/ledger/accounts/{accountId}/balance": {
      "get": {
        "tags": [
          "Ledger"
        ],
        "summary": "Get ledger account balance",
        "operationId": "ledgerBalance",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "accountId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "as_of",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Ledger balance",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/StandardResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/LedgerAccount"
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Account balance snapshot",
                    "value": {
                      "data": {
                        "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                        "code": "1000",
                        "name": "Cash and Cash Equivalents",
                        "account_type": "asset",
                        "currency": "XAF",
                        "account_id": "acc_01HZX9TRJ4M7YQK6P3W2VBDN5K",
                        "balances": [
                          {
                            "type": "ClosingAvailable",
                            "amount": "125000",
                            "credit_debit_indicator": "Credit",
                            "datetime": "2026-05-02T10:15:30Z"
                          },
                          {
                            "type": "ClosingBooked",
                            "amount": "130000",
                            "credit_debit_indicator": "Credit",
                            "datetime": "2026-05-02T10:15:30Z"
                          }
                        ]
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Get ledger account balance.\n\n**Tag:** Ledger\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/ledger/accounts/{accountId}/balance\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/ledger/accounts/{accountId}/balance',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/ledger/accounts/{accountId}/balance\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/ledger/accounts/{accountId}/balance',\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/ledger/journal": {
      "post": {
        "tags": [
          "Ledger"
        ],
        "summary": "Post journal entry",
        "description": "Post a balanced double-entry journal entry. The sum of `lines[].debit` MUST equal the sum of `lines[].credit`; unbalanced submissions are rejected with 422 `journal_entry_unbalanced` and no ledger state is mutated. Entry identifiers and timestamps are assigned by the server and MUST NOT be supplied by the client. All postings are idempotent on the `Idempotency-Key` header.",
        "operationId": "journalPost",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/JournalEntryCreateRequest"
              },
              "example": {
                "entry_date": "2026-05-02",
                "description": "Loan disbursement - APP-2026-001",
                "reference_type": "loan",
                "reference_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                "lines": [
                  {
                    "ledger_account_id": "1f9a3c07-5c2d-4c0a-9d3b-6f8e1a2b3c4d",
                    "debit": 1000000,
                    "credit": 0,
                    "memo": "Loan principal"
                  },
                  {
                    "ledger_account_id": "2a8b4d16-6d3e-4b1b-8e4c-7a9f2b3c4d5e",
                    "debit": 0,
                    "credit": 1000000,
                    "memo": "Cash disbursed"
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Journal entry posted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JournalEntry"
                },
                "examples": {
                  "default": {
                    "summary": "Successful response envelope",
                    "value": {
                      "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                      "entry_date": "2026-05-02",
                      "description": "Loan disbursement - APP-2026-001",
                      "reference_type": "payment",
                      "reference_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                      "success": true,
                      "data": {
                        "id": "obj_01HZX9TRJ4M7YQK6P3W2VBDN5K",
                        "object": "resource",
                        "created_at": "2026-05-02T10:15:30Z"
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "lines": [
                        {
                          "ledger_account_id": "1f9a3c07-5c2d-4c0a-9d3b-6f8e1a2b3c4d",
                          "debit": 1000000,
                          "credit": 0,
                          "memo": "Loan principal"
                        },
                        {
                          "ledger_account_id": "2a8b4d16-6d3e-4b1b-8e4c-7a9f2b3c4d5e",
                          "debit": 0,
                          "credit": 1000000,
                          "memo": "Cash disbursed"
                        }
                      ],
                      "created_at": "2026-05-02T10:15:30Z"
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable entity — journal entry does not balance or references an unknown ledger account",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnprocessable"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/ledger/journal\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/ledger/journal',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/ledger/journal\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/ledger/journal',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      },
      "get": {
        "tags": [
          "Ledger"
        ],
        "summary": "List journal entries",
        "operationId": "journalList",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 25,
              "maximum": 100
            },
            "description": "Items per page"
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 0
            },
            "description": "Items to skip"
          },
          {
            "name": "sort_by",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "created_at"
            },
            "description": "Sort field"
          },
          {
            "name": "sort_order",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "asc",
                "desc"
              ],
              "default": "desc"
            },
            "description": "Sort direction"
          },
          {
            "name": "reference_type",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/StartingAfter"
          },
          {
            "$ref": "#/components/parameters/EndingBefore"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Journal entries",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/JournalEntry"
                          }
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Successful response envelope",
                    "value": {
                      "data": [
                        {
                          "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "entry_date": "2026-05-02",
                          "description": "Loan disbursement - APP-2026-001",
                          "reference_type": "payment",
                          "reference_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "lines": [
                            {
                              "ledger_account_id": "1f9a3c07-5c2d-4c0a-9d3b-6f8e1a2b3c4d",
                              "debit": 1000000,
                              "credit": 0,
                              "memo": "Loan principal"
                            },
                            {
                              "ledger_account_id": "2a8b4d16-6d3e-4b1b-8e4c-7a9f2b3c4d5e",
                              "debit": 0,
                              "credit": 1000000,
                              "memo": "Cash disbursed"
                            }
                          ],
                          "created_at": "2026-05-02T10:15:30Z"
                        }
                      ],
                      "pagination": {
                        "page": 1,
                        "limit": 20,
                        "total": 150,
                        "has_next": true
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "List journal entries.\n\n**Tag:** Ledger\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/ledger/journal\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/ledger/journal',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/ledger/journal\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/ledger/journal',\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/mobile-money/charge": {
      "post": {
        "tags": [
          "Mobile Money"
        ],
        "summary": "Charge mobile money",
        "operationId": "mobileMoneyCharge",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "deprecated": true,
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "phone_number",
                  "amount"
                ],
                "properties": {
                  "phone_number": {
                    "type": "string",
                    "example": "237650000000"
                  },
                  "amount": {
                    "type": "string",
                    "example": "5000",
                    "pattern": "^[0-9]{1,15}$",
                    "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits). Must be consistent with the currency field."
                  },
                  "currency": {
                    "type": "string",
                    "example": "XAF",
                    "enum": [
                      "XAF",
                      "XOF",
                      "USD",
                      "EUR",
                      "GBP",
                      "CNY",
                      "NGN",
                      "GHS",
                      "KES",
                      "ZAR"
                    ],
                    "default": "XAF",
                    "description": "ISO 4217 currency code. Default is XAF (Central African CFA Franc)."
                  },
                  "provider": {
                    "type": "string",
                    "enum": [
                      "MTN",
                      "Orange"
                    ]
                  }
                }
              },
              "example": {
                "phone_number": "237650000000",
                "amount": "5000",
                "currency": "XAF",
                "provider": "MTN"
              }
            }
          }
        },
        "responses": {
          "400": {
            "description": "400 Bad Request — the request failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://api.kangopenbanking.com/v1/errors/validation-error",
                  "title": "Validation Error",
                  "status": 400
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://api.kangopenbanking.com/v1/errors/validation-error",
                  "title": "Validation Error",
                  "status": 400
                }
              }
            }
          },
          "401": {
            "description": "401 Unauthorized — credentials are missing, expired or invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://api.kangopenbanking.com/v1/errors/unauthorized",
                  "title": "Unauthorized",
                  "status": 401
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://api.kangopenbanking.com/v1/errors/unauthorized",
                  "title": "Unauthorized",
                  "status": 401
                }
              }
            }
          },
          "409": {
            "$ref": "#/components/responses/Conflict",
            "headers": {
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "410": {
            "description": "Gone — use /v1/gateway/charges?channel=mobile_money",
            "headers": {
              "Sunset": {
                "schema": {
                  "type": "string"
                },
                "description": "RFC 8594 sunset date (2026-01-01)."
              },
              "Link": {
                "schema": {
                  "type": "string"
                },
                "description": "</v1/gateway/charges?channel=mobile_money>; rel=\"successor-version\""
              },
              "Deprecation": {
                "schema": {
                  "type": "string"
                },
                "description": "true"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "error": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "422": {
            "description": "Provider declined or upstream validation error (normalized).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "error": {
                    "$ref": "#/components/examples/ErrorUnprocessable"
                  }
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests",
            "headers": {
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "500": {
            "description": "500 Internal Server Error — an unexpected condition prevented completion.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://api.kangopenbanking.com/v1/errors/internal-error",
                  "title": "Internal Server Error",
                  "status": 500
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://api.kangopenbanking.com/v1/errors/internal-error",
                  "title": "Internal Server Error",
                  "status": 500
                }
              }
            }
          }
        },
        "description": "**RETIRED on 2026-01-01.** This endpoint returns HTTP 410 Gone. Use `/v1/gateway/charges?channel=mobile_money` instead.\n\nDEPRECATED (sunset: 2026-01-01): Use the unified Payment Gateway at /v1/gateway/charges instead.  Responses will conform to the StandardResponse envelope in a future minor release.\n\n**Migration:** Replace with `gatewayCreateCharge`. Create a charge with `channel=mobile_money`.",
        "x-sunset": "2026-01-01",
        "x-replaced-by": "/v1/gateway/charges (channel: momo)",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/mobile-money/charge\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/mobile-money/charge',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/mobile-money/charge\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/mobile-money/charge',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ],
        "x-retired": true,
        "x-sunset-date": "2026-01-01",
        "x-successor": "/v1/gateway/charges?channel=mobile_money",
        "x-replacement-endpoint": "/v1/gateway/charges?channel=mobile_money",
        "x-replacement-operation-ids": [
          "gatewayCreateCharge"
        ],
        "x-migration-guide": "Create a charge with `channel=mobile_money`."
      }
    },
    "/v1/mobile-money/transfer": {
      "post": {
        "tags": [
          "Mobile Money"
        ],
        "summary": "Transfer to mobile money",
        "operationId": "mobileMoneyTransfer",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "deprecated": true,
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "phone_number",
                  "amount"
                ],
                "properties": {
                  "phone_number": {
                    "type": "string"
                  },
                  "amount": {
                    "type": "string",
                    "example": "10000",
                    "pattern": "^[0-9]{1,15}$",
                    "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits). Must be consistent with the currency field."
                  },
                  "currency": {
                    "type": "string",
                    "example": "XAF",
                    "enum": [
                      "XAF",
                      "XOF",
                      "USD",
                      "EUR",
                      "GBP",
                      "CNY",
                      "NGN",
                      "GHS",
                      "KES",
                      "ZAR"
                    ],
                    "default": "XAF",
                    "description": "ISO 4217 currency code. Default is XAF (Central African CFA Franc)."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "400": {
            "description": "400 Bad Request — the request failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://api.kangopenbanking.com/v1/errors/validation-error",
                  "title": "Validation Error",
                  "status": 400
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://api.kangopenbanking.com/v1/errors/validation-error",
                  "title": "Validation Error",
                  "status": 400
                }
              }
            }
          },
          "401": {
            "description": "401 Unauthorized — credentials are missing, expired or invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://api.kangopenbanking.com/v1/errors/unauthorized",
                  "title": "Unauthorized",
                  "status": 401
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://api.kangopenbanking.com/v1/errors/unauthorized",
                  "title": "Unauthorized",
                  "status": 401
                }
              }
            }
          },
          "409": {
            "$ref": "#/components/responses/Conflict",
            "headers": {
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "410": {
            "description": "Gone — use /v1/gateway/payouts?channel=mobile_money",
            "headers": {
              "Sunset": {
                "schema": {
                  "type": "string"
                },
                "description": "RFC 8594 sunset date (2026-01-01)."
              },
              "Link": {
                "schema": {
                  "type": "string"
                },
                "description": "</v1/gateway/payouts?channel=mobile_money>; rel=\"successor-version\""
              },
              "Deprecation": {
                "schema": {
                  "type": "string"
                },
                "description": "true"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "error": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "422": {
            "description": "Provider declined or upstream validation error (normalized).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "error": {
                    "$ref": "#/components/examples/ErrorUnprocessable"
                  }
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests",
            "headers": {
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "500": {
            "description": "500 Internal Server Error — an unexpected condition prevented completion.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://api.kangopenbanking.com/v1/errors/internal-error",
                  "title": "Internal Server Error",
                  "status": 500
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://api.kangopenbanking.com/v1/errors/internal-error",
                  "title": "Internal Server Error",
                  "status": 500
                }
              }
            }
          }
        },
        "x-sunset": "2026-01-01",
        "x-replaced-by": "/v1/gateway/charges (channel: momo)",
        "description": "**RETIRED on 2026-01-01.** This endpoint returns HTTP 410 Gone. Use `/v1/gateway/payouts?channel=mobile_money` instead.\n\nDEPRECATED (sunset: 2026-01-01): Use the unified Payment Gateway at /v1/gateway/charges instead. \n\n**Migration:** Replace with `gatewayCreatePayout`. Create a payout with `channel=mobile_money`.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/mobile-money/transfer\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/mobile-money/transfer',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/mobile-money/transfer\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/mobile-money/transfer',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ],
        "x-retired": true,
        "x-sunset-date": "2026-01-01",
        "x-successor": "/v1/gateway/payouts?channel=mobile_money",
        "x-replacement-endpoint": "/v1/gateway/payouts?channel=mobile_money",
        "x-replacement-operation-ids": [
          "gatewayCreatePayout"
        ],
        "x-migration-guide": "Create a payout with `channel=mobile_money`."
      }
    },
    "/v1/mobile-money/verify": {
      "post": {
        "tags": [
          "Mobile Money"
        ],
        "summary": "Verify mobile money transaction",
        "operationId": "mobileMoneyVerify",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "deprecated": true,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "transaction_ref"
                ],
                "properties": {
                  "transaction_ref": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "400": {
            "description": "400 Bad Request — the request failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://api.kangopenbanking.com/v1/errors/validation-error",
                  "title": "Validation Error",
                  "status": 400
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://api.kangopenbanking.com/v1/errors/validation-error",
                  "title": "Validation Error",
                  "status": 400
                }
              }
            }
          },
          "401": {
            "description": "401 Unauthorized — credentials are missing, expired or invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://api.kangopenbanking.com/v1/errors/unauthorized",
                  "title": "Unauthorized",
                  "status": 401
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://api.kangopenbanking.com/v1/errors/unauthorized",
                  "title": "Unauthorized",
                  "status": 401
                }
              }
            }
          },
          "409": {
            "$ref": "#/components/responses/Conflict",
            "headers": {
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "410": {
            "description": "Gone — use /v1/gateway/charges/{chargeId}",
            "headers": {
              "Sunset": {
                "schema": {
                  "type": "string"
                },
                "description": "RFC 8594 sunset date (2026-01-01)."
              },
              "Link": {
                "schema": {
                  "type": "string"
                },
                "description": "</v1/gateway/charges/{chargeId}>; rel=\"successor-version\""
              },
              "Deprecation": {
                "schema": {
                  "type": "string"
                },
                "description": "true"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "error": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "422": {
            "description": "Provider declined or upstream validation error (normalized).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "error": {
                    "$ref": "#/components/examples/ErrorUnprocessable"
                  }
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests",
            "headers": {
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "500": {
            "description": "500 Internal Server Error — an unexpected condition prevented completion.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://api.kangopenbanking.com/v1/errors/internal-error",
                  "title": "Internal Server Error",
                  "status": 500
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://api.kangopenbanking.com/v1/errors/internal-error",
                  "title": "Internal Server Error",
                  "status": 500
                }
              }
            }
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "x-sunset": "2026-01-01",
        "x-replaced-by": "/v1/gateway/charges (channel: momo)",
        "description": "**RETIRED on 2026-01-01.** This endpoint returns HTTP 410 Gone. Use `/v1/gateway/charges/{chargeId}` instead.\n\nDEPRECATED (sunset: 2026-01-01): Use the unified Payment Gateway at /v1/gateway/charges instead. \n\n**Migration:** Replace with `gatewayGetCharge`. Retrieve the charge status by `chargeId`.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/mobile-money/verify\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/mobile-money/verify',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/mobile-money/verify\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/mobile-money/verify',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ],
        "x-retired": true,
        "x-sunset-date": "2026-01-01",
        "x-successor": "/v1/gateway/charges/{chargeId}",
        "x-replacement-endpoint": "/v1/gateway/charges/{chargeId}",
        "x-replacement-operation-ids": [
          "gatewayGetCharge"
        ],
        "x-migration-guide": "Retrieve the charge status by `chargeId`."
      }
    },
    "/v1/mobile-money/to-bank": {
      "post": {
        "tags": [
          "Mobile Money"
        ],
        "summary": "Mobile money to bank transfer",
        "operationId": "mobileMoneyToBank",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "deprecated": true,
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "phone_number",
                  "amount",
                  "bank_account"
                ],
                "properties": {
                  "phone_number": {
                    "type": "string"
                  },
                  "amount": {
                    "type": "string",
                    "pattern": "^[0-9]{1,15}$",
                    "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits)."
                  },
                  "bank_account": {
                    "type": "string"
                  },
                  "bank_code": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "400": {
            "description": "400 Bad Request — the request failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://api.kangopenbanking.com/v1/errors/validation-error",
                  "title": "Validation Error",
                  "status": 400
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://api.kangopenbanking.com/v1/errors/validation-error",
                  "title": "Validation Error",
                  "status": 400
                }
              }
            }
          },
          "401": {
            "description": "401 Unauthorized — credentials are missing, expired or invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://api.kangopenbanking.com/v1/errors/unauthorized",
                  "title": "Unauthorized",
                  "status": 401
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://api.kangopenbanking.com/v1/errors/unauthorized",
                  "title": "Unauthorized",
                  "status": 401
                }
              }
            }
          },
          "409": {
            "$ref": "#/components/responses/Conflict",
            "headers": {
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "410": {
            "description": "Gone — use /v1/gateway/payouts?channel=bank_transfer",
            "headers": {
              "Sunset": {
                "schema": {
                  "type": "string"
                },
                "description": "RFC 8594 sunset date (2026-01-01)."
              },
              "Link": {
                "schema": {
                  "type": "string"
                },
                "description": "</v1/gateway/payouts?channel=bank_transfer>; rel=\"successor-version\""
              },
              "Deprecation": {
                "schema": {
                  "type": "string"
                },
                "description": "true"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "error": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "422": {
            "description": "Provider declined or upstream validation error (normalized).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "error": {
                    "$ref": "#/components/examples/ErrorUnprocessable"
                  }
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests",
            "headers": {
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "500": {
            "description": "500 Internal Server Error — an unexpected condition prevented completion.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://api.kangopenbanking.com/v1/errors/internal-error",
                  "title": "Internal Server Error",
                  "status": 500
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://api.kangopenbanking.com/v1/errors/internal-error",
                  "title": "Internal Server Error",
                  "status": 500
                }
              }
            }
          }
        },
        "x-sunset": "2026-01-01",
        "x-replaced-by": "/v1/gateway/charges (channel: momo)",
        "description": "**RETIRED on 2026-01-01.** This endpoint returns HTTP 410 Gone. Use `/v1/gateway/payouts?channel=bank_transfer` instead.\n\nDEPRECATED (sunset: 2026-01-01): Use the unified Payment Gateway at /v1/gateway/charges instead. \n\n**Migration:** Replace with `gatewayCreatePayout`. Create a payout with `channel=bank_transfer`.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/mobile-money/to-bank\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/mobile-money/to-bank',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/mobile-money/to-bank\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/mobile-money/to-bank',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ],
        "x-retired": true,
        "x-sunset-date": "2026-01-01",
        "x-successor": "/v1/gateway/payouts?channel=bank_transfer",
        "x-replacement-endpoint": "/v1/gateway/payouts?channel=bank_transfer",
        "x-replacement-operation-ids": [
          "gatewayCreatePayout"
        ],
        "x-migration-guide": "Create a payout with `channel=bank_transfer`."
      }
    },
    "/v1/flutterwave/bank-transfer": {
      "post": {
        "tags": [
          "Payments"
        ],
        "summary": "Initiate bank transfer via Flutterwave",
        "operationId": "flutterwaveBankTransfer",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "deprecated": true,
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "account_number",
                  "bank_code",
                  "amount"
                ],
                "properties": {
                  "account_number": {
                    "type": "string"
                  },
                  "bank_code": {
                    "type": "string"
                  },
                  "amount": {
                    "type": "string",
                    "example": "100000",
                    "pattern": "^[0-9]{1,15}$",
                    "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits). Must be consistent with the currency field."
                  },
                  "currency": {
                    "type": "string",
                    "example": "XAF",
                    "enum": [
                      "XAF",
                      "XOF",
                      "USD",
                      "EUR",
                      "GBP",
                      "CNY",
                      "NGN",
                      "GHS",
                      "KES",
                      "ZAR"
                    ],
                    "default": "XAF",
                    "description": "ISO 4217 currency code. Default is XAF (Central African CFA Franc)."
                  },
                  "narration": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "400": {
            "description": "400 Bad Request — the request failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://api.kangopenbanking.com/v1/errors/validation-error",
                  "title": "Validation Error",
                  "status": 400
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://api.kangopenbanking.com/v1/errors/validation-error",
                  "title": "Validation Error",
                  "status": 400
                }
              }
            }
          },
          "401": {
            "description": "401 Unauthorized — credentials are missing, expired or invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://api.kangopenbanking.com/v1/errors/unauthorized",
                  "title": "Unauthorized",
                  "status": 401
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://api.kangopenbanking.com/v1/errors/unauthorized",
                  "title": "Unauthorized",
                  "status": 401
                }
              }
            }
          },
          "409": {
            "$ref": "#/components/responses/Conflict",
            "headers": {
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "410": {
            "description": "Gone — use /v1/gateway/payouts?provider=flutterwave",
            "headers": {
              "Sunset": {
                "schema": {
                  "type": "string"
                },
                "description": "RFC 8594 sunset date (2026-01-01)."
              },
              "Link": {
                "schema": {
                  "type": "string"
                },
                "description": "</v1/gateway/payouts?provider=flutterwave>; rel=\"successor-version\""
              },
              "Deprecation": {
                "schema": {
                  "type": "string"
                },
                "description": "true"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "error": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests",
            "headers": {
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "500": {
            "description": "500 Internal Server Error — an unexpected condition prevented completion.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://api.kangopenbanking.com/v1/errors/internal-error",
                  "title": "Internal Server Error",
                  "status": 500
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://api.kangopenbanking.com/v1/errors/internal-error",
                  "title": "Internal Server Error",
                  "status": 500
                }
              }
            }
          }
        },
        "x-sunset": "2026-01-01",
        "x-replaced-by": "/v1/gateway/charges (channel: flutterwave)",
        "description": "**RETIRED on 2026-01-01.** This endpoint returns HTTP 410 Gone. Use `/v1/gateway/payouts?provider=flutterwave` instead.\n\nDEPRECATED (sunset: 2026-01-01): Use the unified Payment Gateway at /v1/gateway/charges instead. \n\n**Migration:** Replace with `gatewayCreatePayout`. Create a payout; provider routing is selected server-side.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/flutterwave/bank-transfer\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/flutterwave/bank-transfer',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/flutterwave/bank-transfer\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/flutterwave/bank-transfer',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ],
        "x-retired": true,
        "x-sunset-date": "2026-01-01",
        "x-successor": "/v1/gateway/payouts?provider=flutterwave",
        "x-replacement-endpoint": "/v1/gateway/payouts?provider=flutterwave",
        "x-replacement-operation-ids": [
          "gatewayCreatePayout"
        ],
        "x-migration-guide": "Create a payout; provider routing is selected server-side."
      }
    },
    "/v1/flutterwave/banks": {
      "get": {
        "tags": [
          "Payments"
        ],
        "summary": "List supported banks",
        "operationId": "flutterwaveListBanks",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "deprecated": true,
        "parameters": [
          {
            "name": "country",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "CM"
            }
          },
          {
            "$ref": "#/components/parameters/PageParam"
          },
          {
            "$ref": "#/components/parameters/LimitParam"
          },
          {
            "$ref": "#/components/parameters/CursorParam"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "400": {
            "description": "400 Bad Request — the request failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://api.kangopenbanking.com/v1/errors/validation-error",
                  "title": "Validation Error",
                  "status": 400
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://api.kangopenbanking.com/v1/errors/validation-error",
                  "title": "Validation Error",
                  "status": 400
                }
              }
            }
          },
          "401": {
            "description": "401 Unauthorized — credentials are missing, expired or invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://api.kangopenbanking.com/v1/errors/unauthorized",
                  "title": "Unauthorized",
                  "status": 401
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://api.kangopenbanking.com/v1/errors/unauthorized",
                  "title": "Unauthorized",
                  "status": 401
                }
              }
            }
          },
          "410": {
            "description": "Gone — use /v1/banks/directory",
            "headers": {
              "Sunset": {
                "schema": {
                  "type": "string"
                },
                "description": "RFC 8594 sunset date (2026-01-01)."
              },
              "Link": {
                "schema": {
                  "type": "string"
                },
                "description": "</v1/banks/directory>; rel=\"successor-version\""
              },
              "Deprecation": {
                "schema": {
                  "type": "string"
                },
                "description": "true"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "error": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded. Retry after the interval in `Retry-After`.",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait before retrying."
              },
              "X-RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "rateLimited": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "500 Internal Server Error — an unexpected condition prevented completion.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://api.kangopenbanking.com/v1/errors/internal-error",
                  "title": "Internal Server Error",
                  "status": 500
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://api.kangopenbanking.com/v1/errors/internal-error",
                  "title": "Internal Server Error",
                  "status": 500
                }
              }
            }
          }
        },
        "x-sunset": "2026-01-01",
        "x-replaced-by": "/v1/gateway/charges (channel: flutterwave)",
        "description": "**RETIRED on 2026-01-01.** This endpoint returns HTTP 410 Gone. Use `GET /v1/directory/banks` (`directoryBanksList`) instead.\n\nDEPRECATED (sunset: 2026-01-01): Use the unified Payment Gateway at /v1/gateway/charges instead. \n\n**Migration:** Replace with `directoryBanksList`. List banks from the KOB bank directory.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/flutterwave/banks\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/flutterwave/banks',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/flutterwave/banks\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/flutterwave/banks',\n]);\n\nprint_r($response->data);"
          }
        ],
        "x-retired": true,
        "x-sunset-date": "2026-01-01",
        "x-successor": "/v1/banks/directory",
        "x-replacement-endpoint": "/v1/banks/directory",
        "x-replacement-operation-ids": [
          "directoryBanksList"
        ],
        "x-migration-guide": "List banks from the KOB bank directory."
      }
    },
    "/v1/flutterwave/verify-bank": {
      "post": {
        "tags": [
          "Payments"
        ],
        "summary": "Verify bank account",
        "operationId": "flutterwaveVerifyBank",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "deprecated": true,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "account_number",
                  "bank_code"
                ],
                "properties": {
                  "account_number": {
                    "type": "string"
                  },
                  "bank_code": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "400": {
            "description": "400 Bad Request — the request failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://api.kangopenbanking.com/v1/errors/validation-error",
                  "title": "Validation Error",
                  "status": 400
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://api.kangopenbanking.com/v1/errors/validation-error",
                  "title": "Validation Error",
                  "status": 400
                }
              }
            }
          },
          "401": {
            "description": "401 Unauthorized — credentials are missing, expired or invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://api.kangopenbanking.com/v1/errors/unauthorized",
                  "title": "Unauthorized",
                  "status": 401
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://api.kangopenbanking.com/v1/errors/unauthorized",
                  "title": "Unauthorized",
                  "status": 401
                }
              }
            }
          },
          "409": {
            "$ref": "#/components/responses/Conflict",
            "headers": {
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "410": {
            "description": "Gone — use /v1/banks/verify-account",
            "headers": {
              "Sunset": {
                "schema": {
                  "type": "string"
                },
                "description": "RFC 8594 sunset date (2026-01-01)."
              },
              "Link": {
                "schema": {
                  "type": "string"
                },
                "description": "</v1/banks/verify-account>; rel=\"successor-version\""
              },
              "Deprecation": {
                "schema": {
                  "type": "string"
                },
                "description": "true"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "error": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests",
            "headers": {
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "500": {
            "description": "500 Internal Server Error — an unexpected condition prevented completion.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://api.kangopenbanking.com/v1/errors/internal-error",
                  "title": "Internal Server Error",
                  "status": 500
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://api.kangopenbanking.com/v1/errors/internal-error",
                  "title": "Internal Server Error",
                  "status": 500
                }
              }
            }
          }
        },
        "x-sunset": "2026-01-01",
        "x-replaced-by": "/v1/gateway/charges (channel: flutterwave)",
        "description": "**RETIRED on 2026-01-01.** This endpoint returns HTTP 410 Gone. No direct replacement exists; see Migration below.\n\nDEPRECATED (sunset: 2026-01-01): Use the unified Payment Gateway at /v1/gateway/charges instead. \n\n**Migration:** No direct replacement. Validate destination details when creating a payout with `gatewayCreatePayout`; validation failures are returned as Problem Details.",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Recommended for safe retries. UUID v4. When supplied, duplicate requests within 24h replay the original response. See Idempotency guide."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/flutterwave/verify-bank\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/flutterwave/verify-bank',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/flutterwave/verify-bank\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/flutterwave/verify-bank',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ],
        "x-retired": true,
        "x-sunset-date": "2026-01-01",
        "x-successor": "/v1/banks/verify-account",
        "x-replacement-endpoint": "/v1/banks/verify-account",
        "x-replacement-operation-ids": [],
        "x-migration-guide": "No direct replacement. Validate destination details when creating a payout with `gatewayCreatePayout`; validation failures are returned as Problem Details."
      }
    },
    "/v1/stripe/payment-intent": {
      "post": {
        "tags": [
          "Payments"
        ],
        "summary": "Create Stripe payment intent",
        "operationId": "stripePaymentIntent",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "deprecated": true,
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "amount",
                  "currency"
                ],
                "properties": {
                  "amount": {
                    "type": "string",
                    "pattern": "^[0-9]{1,15}$",
                    "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits). Must be consistent with the currency field."
                  },
                  "currency": {
                    "type": "string",
                    "example": "XAF",
                    "enum": [
                      "XAF",
                      "XOF",
                      "USD",
                      "EUR",
                      "GBP",
                      "CNY",
                      "NGN",
                      "GHS",
                      "KES",
                      "ZAR"
                    ],
                    "default": "XAF",
                    "description": "ISO 4217 currency code. Default is XAF (Central African CFA Franc)."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "400": {
            "description": "400 Bad Request — the request failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://api.kangopenbanking.com/v1/errors/validation-error",
                  "title": "Validation Error",
                  "status": 400
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://api.kangopenbanking.com/v1/errors/validation-error",
                  "title": "Validation Error",
                  "status": 400
                }
              }
            }
          },
          "401": {
            "description": "401 Unauthorized — credentials are missing, expired or invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://api.kangopenbanking.com/v1/errors/unauthorized",
                  "title": "Unauthorized",
                  "status": 401
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://api.kangopenbanking.com/v1/errors/unauthorized",
                  "title": "Unauthorized",
                  "status": 401
                }
              }
            }
          },
          "409": {
            "$ref": "#/components/responses/Conflict",
            "headers": {
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "410": {
            "description": "Gone — use /v1/gateway/charges?provider=stripe",
            "headers": {
              "Sunset": {
                "schema": {
                  "type": "string"
                },
                "description": "RFC 8594 sunset date (2026-01-01)."
              },
              "Link": {
                "schema": {
                  "type": "string"
                },
                "description": "</v1/gateway/charges?provider=stripe>; rel=\"successor-version\""
              },
              "Deprecation": {
                "schema": {
                  "type": "string"
                },
                "description": "true"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "error": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests",
            "headers": {
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "500": {
            "description": "500 Internal Server Error — an unexpected condition prevented completion.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://api.kangopenbanking.com/v1/errors/internal-error",
                  "title": "Internal Server Error",
                  "status": 500
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://api.kangopenbanking.com/v1/errors/internal-error",
                  "title": "Internal Server Error",
                  "status": 500
                }
              }
            }
          }
        },
        "x-sunset": "2026-01-01",
        "x-replaced-by": "/v1/gateway/charges (channel: stripe)",
        "description": "**RETIRED on 2026-01-01.** This endpoint returns HTTP 410 Gone. Use `/v1/gateway/charges?provider=stripe` instead.\n\nDEPRECATED (sunset: 2026-01-01): Use the unified Payment Gateway at /v1/gateway/charges instead. \n\n**Migration:** Replace with `gatewayCreateCharge`. Create a card charge; card details are collected only through Stripe Elements.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/stripe/payment-intent\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/stripe/payment-intent',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/stripe/payment-intent\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/stripe/payment-intent',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ],
        "x-retired": true,
        "x-sunset-date": "2026-01-01",
        "x-successor": "/v1/gateway/charges?provider=stripe",
        "x-replacement-endpoint": "/v1/gateway/charges?provider=stripe",
        "x-replacement-operation-ids": [
          "gatewayCreateCharge"
        ],
        "x-migration-guide": "Create a card charge; card details are collected only through Stripe Elements."
      }
    },
    "/v1/stripe/confirm-payment": {
      "post": {
        "tags": [
          "Payments"
        ],
        "summary": "Confirm Stripe payment",
        "operationId": "stripeConfirmPayment",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "deprecated": true,
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "payment_intent_id"
                ],
                "properties": {
                  "payment_intent_id": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "400": {
            "description": "400 Bad Request — the request failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://api.kangopenbanking.com/v1/errors/validation-error",
                  "title": "Validation Error",
                  "status": 400
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://api.kangopenbanking.com/v1/errors/validation-error",
                  "title": "Validation Error",
                  "status": 400
                }
              }
            }
          },
          "401": {
            "description": "401 Unauthorized — credentials are missing, expired or invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://api.kangopenbanking.com/v1/errors/unauthorized",
                  "title": "Unauthorized",
                  "status": 401
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://api.kangopenbanking.com/v1/errors/unauthorized",
                  "title": "Unauthorized",
                  "status": 401
                }
              }
            }
          },
          "409": {
            "$ref": "#/components/responses/Conflict",
            "headers": {
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "410": {
            "description": "Gone — use /v1/gateway/charges/{chargeId}",
            "headers": {
              "Sunset": {
                "schema": {
                  "type": "string"
                },
                "description": "RFC 8594 sunset date (2026-01-01)."
              },
              "Link": {
                "schema": {
                  "type": "string"
                },
                "description": "</v1/gateway/charges/{chargeId}>; rel=\"successor-version\""
              },
              "Deprecation": {
                "schema": {
                  "type": "string"
                },
                "description": "true"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "error": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests",
            "headers": {
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "500": {
            "description": "500 Internal Server Error — an unexpected condition prevented completion.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://api.kangopenbanking.com/v1/errors/internal-error",
                  "title": "Internal Server Error",
                  "status": 500
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://api.kangopenbanking.com/v1/errors/internal-error",
                  "title": "Internal Server Error",
                  "status": 500
                }
              }
            }
          }
        },
        "x-sunset": "2026-01-01",
        "x-replaced-by": "/v1/gateway/charges (channel: stripe)",
        "description": "**RETIRED on 2026-01-01.** This endpoint returns HTTP 410 Gone. Use `/v1/gateway/charges/{chargeId}` instead.\n\nDEPRECATED (sunset: 2026-01-01): Use the unified Payment Gateway at /v1/gateway/charges instead. \n\n**Migration:** Replace with `gatewayGetCharge`. Retrieve the charge status by `chargeId`.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/stripe/confirm-payment\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/stripe/confirm-payment',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/stripe/confirm-payment\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/stripe/confirm-payment',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ],
        "x-retired": true,
        "x-sunset-date": "2026-01-01",
        "x-successor": "/v1/gateway/charges/{chargeId}",
        "x-replacement-endpoint": "/v1/gateway/charges/{chargeId}",
        "x-replacement-operation-ids": [
          "gatewayGetCharge"
        ],
        "x-migration-guide": "Retrieve the charge status by `chargeId`."
      }
    },
    "/v1/banking/bulk-transfers": {
      "post": {
        "tags": [
          "Banking Operations"
        ],
        "summary": "Initiate bulk transfers",
        "operationId": "bulkTransfers",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "transfers"
                ],
                "properties": {
                  "transfers": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "account_number": {
                          "type": "string"
                        },
                        "bank_code": {
                          "type": "string"
                        },
                        "amount": {
                          "type": "string",
                          "pattern": "^[0-9]{1,15}$",
                          "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits)."
                        },
                        "narration": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Bulk transfer initiated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Initiate bulk transfers.\n\n**Tag:** Banking Operations\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/banking/bulk-transfers\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/banking/bulk-transfers',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/banking/bulk-transfers\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/banking/bulk-transfers',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/banking/exchange-rate": {
      "get": {
        "tags": [
          "Banking Operations"
        ],
        "summary": "Get exchange rate",
        "operationId": "exchangeRate",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "example": "XAF"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "example": "USD"
            }
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Exchange rate",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "from": {
                      "type": "string"
                    },
                    "to": {
                      "type": "string"
                    },
                    "rate": {
                      "type": "number"
                    },
                    "timestamp": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Get exchange rate.\n\n**Tag:** Banking Operations\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/banking/exchange-rate\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/banking/exchange-rate',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/banking/exchange-rate\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/banking/exchange-rate',\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/cards": {
      "post": {
        "tags": [
          "Virtual Cards"
        ],
        "summary": "Create virtual card",
        "operationId": "virtualCardCreate",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "currency": {
                    "type": "string",
                    "example": "USD",
                    "enum": [
                      "XAF",
                      "XOF",
                      "USD",
                      "EUR",
                      "GBP",
                      "CNY",
                      "NGN",
                      "GHS",
                      "KES",
                      "ZAR"
                    ],
                    "default": "XAF",
                    "description": "ISO 4217 currency code. Default is XAF (Central African CFA Franc)."
                  },
                  "label": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Card created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VirtualCard"
                },
                "examples": {
                  "default": {
                    "summary": "Successful response envelope",
                    "value": {
                      "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                      "card_number_masked": "**** **** **** 1234",
                      "status": "active",
                      "success": true,
                      "data": {
                        "id": "obj_01HZX9TRJ4M7YQK6P3W2VBDN5K",
                        "object": "resource",
                        "created_at": "2026-05-02T10:15:30Z"
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      }
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Create virtual card.\n\n**Tag:** Virtual Cards\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/cards\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/cards',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/cards\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/cards',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      },
      "get": {
        "tags": [
          "Virtual Cards"
        ],
        "summary": "List virtual cards",
        "operationId": "virtualCardList",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Cards list",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/VirtualCard"
                          }
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Cursor-paginated list",
                    "value": {
                      "data": [
                        {
                          "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "card_number_masked": "**** **** **** 1234",
                          "status": "active",
                          "object": "resource",
                          "created_at": "2026-05-02T10:15:30Z"
                        },
                        {
                          "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "card_number_masked": "**** **** **** 1234",
                          "status": "active",
                          "object": "resource",
                          "created_at": "2026-05-02T10:15:31Z"
                        }
                      ],
                      "pagination": {
                        "page": 1,
                        "limit": 20,
                        "total": 150,
                        "has_next": true,
                        "has_more": true,
                        "next_cursor": "cursor_01HZX9TRJ4M7YQK6P3W2VBDN5M",
                        "prev_cursor": null,
                        "total_count": 247
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/PageParam"
          },
          {
            "$ref": "#/components/parameters/LimitParam"
          },
          {
            "$ref": "#/components/parameters/CursorParam"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "description": "List virtual cards.\n\n**Tag:** Virtual Cards\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/cards\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/cards',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/cards\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/cards',\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/cards/{cardId}/topup": {
      "post": {
        "tags": [
          "Virtual Cards"
        ],
        "summary": "Top up virtual card",
        "operationId": "virtualCardTopup",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "cardId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "amount",
                  "source_currency"
                ],
                "properties": {
                  "amount": {
                    "type": "string",
                    "example": "50000",
                    "pattern": "^[0-9]{1,15}$",
                    "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits)."
                  },
                  "source_currency": {
                    "type": "string",
                    "example": "XAF"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Card topped up",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Top up virtual card.\n\n**Tag:** Virtual Cards\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/cards/{cardId}/topup\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/cards/{cardId}/topup',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/cards/{cardId}/topup\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/cards/{cardId}/topup',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/cards/{cardId}/transactions": {
      "get": {
        "tags": [
          "Virtual Cards"
        ],
        "summary": "Card transactions",
        "operationId": "virtualCardTransactions",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "cardId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 25,
              "maximum": 100
            },
            "description": "Items per page"
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 0
            },
            "description": "Items to skip"
          },
          {
            "name": "sort_by",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "created_at"
            },
            "description": "Sort field"
          },
          {
            "name": "sort_order",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "asc",
                "desc"
              ],
              "default": "desc"
            },
            "description": "Sort direction"
          },
          {
            "$ref": "#/components/parameters/StartingAfter"
          },
          {
            "$ref": "#/components/parameters/EndingBefore"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Card transactions",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/Transaction"
                          }
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Cursor-paginated list",
                    "value": {
                      "data": [
                        {
                          "transaction_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "amount": "25000",
                          "currency": "XAF",
                          "type": "debit",
                          "timestamp": "2026-05-02T10:15:30Z",
                          "id": "obj_01HZX9TRJ4M7YQK6P3W2VBDN5K",
                          "object": "resource",
                          "created_at": "2026-05-02T10:15:30Z"
                        },
                        {
                          "transaction_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "amount": "25000",
                          "currency": "XAF",
                          "type": "debit",
                          "timestamp": "2026-05-02T10:15:30Z",
                          "id": "obj_01HZX9TRJ4M7YQK6P3W2VBDN5L",
                          "object": "resource",
                          "created_at": "2026-05-02T10:15:31Z"
                        }
                      ],
                      "pagination": {
                        "page": 1,
                        "limit": 20,
                        "total": 150,
                        "has_next": true,
                        "has_more": true,
                        "next_cursor": "cursor_01HZX9TRJ4M7YQK6P3W2VBDN5M",
                        "prev_cursor": null,
                        "total_count": 247
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Card transactions.\n\n**Tag:** Virtual Cards\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/cards/{cardId}/transactions\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/cards/{cardId}/transactions',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/cards/{cardId}/transactions\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/cards/{cardId}/transactions',\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/cards/{cardId}/status": {
      "put": {
        "tags": [
          "Virtual Cards"
        ],
        "summary": "Update card status",
        "operationId": "virtualCardUpdateStatus",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "cardId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "status"
                ],
                "properties": {
                  "status": {
                    "type": "string",
                    "enum": [
                      "active",
                      "frozen",
                      "cancelled"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Status updated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Update card status.\n\n**Tag:** Virtual Cards\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X PUT \"https://api.kangopenbanking.com/v1/cards/{cardId}/status\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'PUT',\n  path: '/v1/cards/{cardId}/status',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"PUT\",\n    path=\"/v1/cards/{cardId}/status\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'PUT',\n    'path'   => '/v1/cards/{cardId}/status',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/standards/iso20022/pain001/parse": {
      "post": {
        "tags": [
          "Standards"
        ],
        "summary": "Parse pain.001",
        "operationId": "iso20022Pain001Parser",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/xml": {
              "schema": {
                "type": "string"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Parsed payment initiation",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message_id": {
                      "type": "string"
                    },
                    "creation_date": {
                      "type": "string"
                    },
                    "payments": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "end_to_end_id": {
                            "type": "string"
                          },
                          "amount": {
                            "type": "string",
                            "pattern": "^[0-9]{1,15}$",
                            "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits). Must be consistent with the currency field."
                          },
                          "currency": {
                            "type": "string",
                            "enum": [
                              "XAF",
                              "XOF",
                              "USD",
                              "EUR",
                              "GBP",
                              "CNY",
                              "NGN",
                              "GHS",
                              "KES",
                              "ZAR"
                            ],
                            "default": "XAF",
                            "description": "ISO 4217 currency code. Default is XAF (Central African CFA Franc)."
                          },
                          "creditor_name": {
                            "type": "string"
                          },
                          "creditor_account": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "x-iso20022-message": "pain.001.001.09",
        "description": "Parse pain.001.\n\n**Tag:** Standards\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/standards/iso20022/pain001/parse\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/standards/iso20022/pain001/parse',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/standards/iso20022/pain001/parse\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/standards/iso20022/pain001/parse',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ]
      }
    },
    "/v1/standards/iso20022/camt053/parse": {
      "post": {
        "tags": [
          "Standards"
        ],
        "summary": "Parse camt.053",
        "operationId": "iso20022Camt053Parser",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/xml": {
              "schema": {
                "type": "string"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Parsed bank statement",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statement_id": {
                      "type": "string"
                    },
                    "account": {
                      "type": "string"
                    },
                    "opening_balance": {
                      "type": "number",
                      "deprecated": true,
                      "x-successor": "opening_balance_money",
                      "x-sunset": "5.0.0",
                      "description": "Deprecated: floating-point monetary value (IEEE-754 binary64 cannot represent decimal minor units exactly). Use `opening_balance_money` instead. Removal is scheduled for v5.0.0."
                    },
                    "closing_balance": {
                      "type": "number",
                      "deprecated": true,
                      "x-successor": "closing_balance_money",
                      "x-sunset": "5.0.0",
                      "description": "Deprecated: floating-point monetary value (IEEE-754 binary64 cannot represent decimal minor units exactly). Use `closing_balance_money` instead. Removal is scheduled for v5.0.0."
                    },
                    "entries": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "amount": {
                            "type": "string",
                            "pattern": "^[0-9]{1,15}$",
                            "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits)."
                          },
                          "credit_debit": {
                            "type": "string"
                          },
                          "booking_date": {
                            "type": "string"
                          },
                          "reference": {
                            "type": "string"
                          }
                        }
                      }
                    },
                    "opening_balance_money": {
                      "$ref": "#/components/schemas/Money",
                      "description": "Canonical string-encoded successor to `opening_balance`. Amount and ISO 4217 currency travel together (ISO 20022 ActiveCurrencyAndAmount). Prefer this field: it is exact for zero-decimal currencies (XAF, XOF) and immune to IEEE-754 drift.",
                      "x-added-in": "4.54.0"
                    },
                    "closing_balance_money": {
                      "$ref": "#/components/schemas/Money",
                      "description": "Canonical string-encoded successor to `closing_balance`. Amount and ISO 4217 currency travel together (ISO 20022 ActiveCurrencyAndAmount). Prefer this field: it is exact for zero-decimal currencies (XAF, XOF) and immune to IEEE-754 drift.",
                      "x-added-in": "4.54.0"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "x-iso20022-message": "camt.053.001.08",
        "description": "Parse camt.053.\n\n**Tag:** Standards\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/standards/iso20022/camt053/parse\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/standards/iso20022/camt053/parse',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/standards/iso20022/camt053/parse\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/standards/iso20022/camt053/parse',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ]
      }
    },
    "/v1/standards/iso20022/pacs008/generate": {
      "post": {
        "tags": [
          "Standards"
        ],
        "summary": "Generate pacs.008",
        "operationId": "iso20022Pacs008Generator",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Generated FI-to-FI payment",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "xml": {
                      "type": "string"
                    },
                    "message_id": {
                      "type": "string"
                    },
                    "transaction_id": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "x-iso20022-message": "pacs.008.001.08",
        "description": "Generate pacs.008.\n\n**Tag:** Standards\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/standards/iso20022/pacs008/generate\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/standards/iso20022/pacs008/generate',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/standards/iso20022/pacs008/generate\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/standards/iso20022/pacs008/generate',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/standards/iso20022/pacs002/generate": {
      "post": {
        "tags": [
          "Standards"
        ],
        "summary": "Generate pacs.002",
        "operationId": "iso20022Pacs002Generator",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Generated payment status report",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "xml": {
                      "type": "string"
                    },
                    "message_id": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "x-iso20022-message": "pacs.002.001.10",
        "description": "Generate pacs.002.\n\n**Tag:** Standards\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/standards/iso20022/pacs002/generate\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/standards/iso20022/pacs002/generate',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/standards/iso20022/pacs002/generate\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/standards/iso20022/pacs002/generate',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/standards/swift/mt103/parse": {
      "post": {
        "tags": [
          "Standards"
        ],
        "summary": "Parse MT103",
        "operationId": "swiftMt103Parser",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "text/plain": {
              "schema": {
                "type": "string"
              }
            }
          }
        },
        "responses": {
          "400": {
            "description": "400 Bad Request — the request failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://api.kangopenbanking.com/v1/errors/validation-error",
                  "title": "Validation Error",
                  "status": 400
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://api.kangopenbanking.com/v1/errors/validation-error",
                  "title": "Validation Error",
                  "status": 400
                }
              }
            }
          },
          "401": {
            "description": "401 Unauthorized — credentials are missing, expired or invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://api.kangopenbanking.com/v1/errors/unauthorized",
                  "title": "Unauthorized",
                  "status": 401
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://api.kangopenbanking.com/v1/errors/unauthorized",
                  "title": "Unauthorized",
                  "status": 401
                }
              }
            }
          },
          "409": {
            "$ref": "#/components/responses/Conflict",
            "headers": {
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "410": {
            "description": "Gone — use /v1/standards/iso20022/pacs008/generate",
            "headers": {
              "Sunset": {
                "schema": {
                  "type": "string"
                },
                "description": "RFC 8594 sunset date (2025-11-22)."
              },
              "Link": {
                "schema": {
                  "type": "string"
                },
                "description": "</v1/standards/iso20022/pacs008/generate>; rel=\"successor-version\""
              },
              "Deprecation": {
                "schema": {
                  "type": "string"
                },
                "description": "true"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "error": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests",
            "headers": {
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "500": {
            "description": "500 Internal Server Error — an unexpected condition prevented completion.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://api.kangopenbanking.com/v1/errors/internal-error",
                  "title": "Internal Server Error",
                  "status": 500
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://api.kangopenbanking.com/v1/errors/internal-error",
                  "title": "Internal Server Error",
                  "status": 500
                }
              }
            }
          }
        },
        "deprecated": true,
        "description": "**RETIRED on 2025-11-22.** This endpoint returns HTTP 410 Gone. Use the ISO 20022 operations listed under Migration below.\n\nDEPRECATED: SWIFT MT messages are being decommissioned as part of the global ISO 20022 migration programme. This endpoint will be removed on 2025-11-22. Please migrate to the equivalent ISO 20022 MX message endpoints: /v1/standards/iso20022/pacs008/generate (replaces MT103) and /v1/standards/iso20022/camt053/parse (replaces MT940). \n\n**Migration:** Replace with `iso20022Pain001Parser`. Submit the equivalent ISO 20022 pain.001 message.",
        "x-sunset": "2025-11-22",
        "x-replaced-by": "/v1/standards/iso20022/pacs008/generate",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/standards/swift/mt103/parse\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/standards/swift/mt103/parse',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/standards/swift/mt103/parse\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/standards/swift/mt103/parse',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ],
        "x-retired": true,
        "x-sunset-date": "2025-11-22",
        "x-successor": "/v1/standards/iso20022/pacs008/generate",
        "x-replacement-endpoint": "/v1/standards/iso20022/pacs008/generate",
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "x-replacement-operation-ids": [
          "iso20022Pain001Parser"
        ],
        "x-migration-guide": "Submit the equivalent ISO 20022 pain.001 message."
      }
    },
    "/v1/standards/swift/mt940/parse": {
      "post": {
        "tags": [
          "Standards"
        ],
        "summary": "Parse MT940",
        "operationId": "swiftMt940Parser",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "text/plain": {
              "schema": {
                "type": "string"
              }
            }
          }
        },
        "responses": {
          "400": {
            "description": "400 Bad Request — the request failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://api.kangopenbanking.com/v1/errors/validation-error",
                  "title": "Validation Error",
                  "status": 400
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://api.kangopenbanking.com/v1/errors/validation-error",
                  "title": "Validation Error",
                  "status": 400
                }
              }
            }
          },
          "401": {
            "description": "401 Unauthorized — credentials are missing, expired or invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://api.kangopenbanking.com/v1/errors/unauthorized",
                  "title": "Unauthorized",
                  "status": 401
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://api.kangopenbanking.com/v1/errors/unauthorized",
                  "title": "Unauthorized",
                  "status": 401
                }
              }
            }
          },
          "409": {
            "$ref": "#/components/responses/Conflict",
            "headers": {
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "410": {
            "description": "Gone — use /v1/standards/iso20022/camt053/parse",
            "headers": {
              "Sunset": {
                "schema": {
                  "type": "string"
                },
                "description": "RFC 8594 sunset date (2025-11-22)."
              },
              "Link": {
                "schema": {
                  "type": "string"
                },
                "description": "</v1/standards/iso20022/camt053/parse>; rel=\"successor-version\""
              },
              "Deprecation": {
                "schema": {
                  "type": "string"
                },
                "description": "true"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "error": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests",
            "headers": {
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "500": {
            "description": "500 Internal Server Error — an unexpected condition prevented completion.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://api.kangopenbanking.com/v1/errors/internal-error",
                  "title": "Internal Server Error",
                  "status": 500
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://api.kangopenbanking.com/v1/errors/internal-error",
                  "title": "Internal Server Error",
                  "status": 500
                }
              }
            }
          }
        },
        "deprecated": true,
        "description": "**RETIRED on 2025-11-22.** This endpoint returns HTTP 410 Gone. Use the ISO 20022 operations listed under Migration below.\n\nDEPRECATED: SWIFT MT messages are being decommissioned as part of the global ISO 20022 migration programme. This endpoint will be removed on 2025-11-22. Please migrate to the equivalent ISO 20022 MX message endpoints: /v1/standards/iso20022/pacs008/generate (replaces MT103) and /v1/standards/iso20022/camt053/parse (replaces MT940). \n\n**Migration:** Replace with `iso20022Camt053Parser`. Submit the equivalent ISO 20022 camt.053 statement.",
        "x-sunset": "2025-11-22",
        "x-replaced-by": "/v1/standards/iso20022/camt053/parse",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/standards/swift/mt940/parse\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/standards/swift/mt940/parse',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/standards/swift/mt940/parse\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/standards/swift/mt940/parse',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ],
        "x-retired": true,
        "x-sunset-date": "2025-11-22",
        "x-successor": "/v1/standards/iso20022/camt053/parse",
        "x-replacement-endpoint": "/v1/standards/iso20022/camt053/parse",
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "x-replacement-operation-ids": [
          "iso20022Camt053Parser"
        ],
        "x-migration-guide": "Submit the equivalent ISO 20022 camt.053 statement."
      }
    },
    "/v1/standards/swift/mt103/generate": {
      "post": {
        "tags": [
          "Standards"
        ],
        "summary": "Generate MT103",
        "operationId": "swiftMt103Generator",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "400": {
            "description": "400 Bad Request — the request failed validation.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://api.kangopenbanking.com/v1/errors/validation-error",
                  "title": "Validation Error",
                  "status": 400
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://api.kangopenbanking.com/v1/errors/validation-error",
                  "title": "Validation Error",
                  "status": 400
                }
              }
            }
          },
          "401": {
            "description": "401 Unauthorized — credentials are missing, expired or invalid.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://api.kangopenbanking.com/v1/errors/unauthorized",
                  "title": "Unauthorized",
                  "status": 401
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://api.kangopenbanking.com/v1/errors/unauthorized",
                  "title": "Unauthorized",
                  "status": 401
                }
              }
            }
          },
          "409": {
            "$ref": "#/components/responses/Conflict",
            "headers": {
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "410": {
            "description": "Gone — use /v1/standards/iso20022/pacs008/generate",
            "headers": {
              "Sunset": {
                "schema": {
                  "type": "string"
                },
                "description": "RFC 8594 sunset date (2025-11-22)."
              },
              "Link": {
                "schema": {
                  "type": "string"
                },
                "description": "</v1/standards/iso20022/pacs008/generate>; rel=\"successor-version\""
              },
              "Deprecation": {
                "schema": {
                  "type": "string"
                },
                "description": "true"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            },
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "error": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests",
            "headers": {
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "500": {
            "description": "500 Internal Server Error — an unexpected condition prevented completion.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://api.kangopenbanking.com/v1/errors/internal-error",
                  "title": "Internal Server Error",
                  "status": 500
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://api.kangopenbanking.com/v1/errors/internal-error",
                  "title": "Internal Server Error",
                  "status": 500
                }
              }
            }
          }
        },
        "deprecated": true,
        "description": "**RETIRED on 2025-11-22.** This endpoint returns HTTP 410 Gone. Use the ISO 20022 operations listed under Migration below.\n\nDEPRECATED: SWIFT MT messages are being decommissioned as part of the global ISO 20022 migration programme. This endpoint will be removed on 2025-11-22. Please migrate to the equivalent ISO 20022 MX message endpoints: /v1/standards/iso20022/pacs008/generate (replaces MT103) and /v1/standards/iso20022/camt053/parse (replaces MT940). \n\n**Migration:** Replace with `interbankPaymentCreate`. Create an interbank payment; ISO 20022 messages are produced server-side and listed by `interbankMessagesList`.",
        "x-sunset": "2025-11-22",
        "x-replaced-by": "/v1/standards/iso20022/pacs008/generate",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/standards/swift/mt103/generate\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/standards/swift/mt103/generate',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/standards/swift/mt103/generate\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/standards/swift/mt103/generate',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ],
        "x-retired": true,
        "x-sunset-date": "2025-11-22",
        "x-successor": "/v1/standards/iso20022/pacs008/generate",
        "x-replacement-endpoint": "/v1/standards/iso20022/pacs008/generate",
        "x-replacement-operation-ids": [
          "interbankPaymentCreate"
        ],
        "x-migration-guide": "Create an interbank payment; ISO 20022 messages are produced server-side and listed by `interbankMessagesList`."
      }
    },
    "/v1/standards/validate/iban": {
      "post": {
        "tags": [
          "Standards"
        ],
        "summary": "Validate IBAN",
        "operationId": "validateIban",
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "iban"
                ],
                "properties": {
                  "iban": {
                    "type": "string",
                    "example": "CM21 10003 00100 0123456789 023"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Validation result",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "valid": {
                      "type": "boolean"
                    },
                    "iban": {
                      "type": "string"
                    },
                    "country": {
                      "type": "string"
                    },
                    "bank_code": {
                      "type": "string"
                    },
                    "errors": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Validate IBAN.\n\n**Tag:** Standards\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/standards/validate/iban\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/standards/validate/iban',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/standards/validate/iban\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/standards/validate/iban',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ]
      }
    },
    "/v1/standards/validate/bic": {
      "post": {
        "tags": [
          "Standards"
        ],
        "summary": "Validate BIC/SWIFT code",
        "operationId": "validateBic",
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "bic"
                ],
                "properties": {
                  "bic": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Validation result",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "valid": {
                      "type": "boolean"
                    },
                    "bic": {
                      "type": "string"
                    },
                    "institution": {
                      "type": "string"
                    },
                    "country": {
                      "type": "string"
                    },
                    "errors": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Validate BIC/SWIFT code.\n\n**Tag:** Standards\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/standards/validate/bic\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/standards/validate/bic',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/standards/validate/bic\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/standards/validate/bic',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ]
      }
    },
    "/v1/standards/validate/rib": {
      "post": {
        "tags": [
          "Standards"
        ],
        "summary": "Validate Cameroon Domestic RIB",
        "operationId": "validateRib",
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "rib"
                ],
                "properties": {
                  "rib": {
                    "type": "string",
                    "example": "10005001000123456789023",
                    "description": "23-digit Cameroon domestic RIB/BBAN"
                  },
                  "country": {
                    "type": "string",
                    "default": "CM"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "RIB validation result with structured fields (bank_code, branch_code, account_number, rib_key), derived IBAN, and bank lookup",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "valid": {
                      "type": "boolean"
                    },
                    "bank_code": {
                      "type": "string",
                      "example": "10005"
                    },
                    "branch_code": {
                      "type": "string",
                      "example": "00100"
                    },
                    "account_number": {
                      "type": "string",
                      "example": "01234567890"
                    },
                    "rib_key": {
                      "type": "string",
                      "example": "23"
                    },
                    "bank_name": {
                      "type": "string",
                      "example": "Afriland First Bank"
                    },
                    "swift_bic": {
                      "type": "string",
                      "example": "AFRIACMCXXX"
                    },
                    "derived_iban": {
                      "type": "string",
                      "example": "CM21 1000 5001 0001 2345 6789 023"
                    },
                    "formatted_display": {
                      "type": "string",
                      "example": "10005-00100-01234567890-23"
                    },
                    "errors": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Validate Cameroon Domestic RIB.\n\n**Tag:** Standards\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/standards/validate/rib\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/standards/validate/rib',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/standards/validate/rib\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/standards/validate/rib',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ]
      }
    },
    "/v1/standards/validate/account-identifier": {
      "post": {
        "tags": [
          "Standards"
        ],
        "summary": "Validate any account identifier (RIB, IBAN, LOCAL_BANK, MOMO)",
        "operationId": "validateAccountIdentifier",
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "type",
                  "value"
                ],
                "properties": {
                  "type": {
                    "type": "string",
                    "enum": [
                      "DOMESTIC_RIB",
                      "IBAN",
                      "LOCAL_BANK",
                      "MOMO"
                    ]
                  },
                  "value": {
                    "type": "string"
                  },
                  "country": {
                    "type": "string",
                    "default": "CM"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Unified validation result with rail determination",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "valid": {
                      "type": "boolean"
                    },
                    "identifier_type": {
                      "type": "string",
                      "enum": [
                        "DOMESTIC_RIB",
                        "IBAN",
                        "LOCAL_BANK",
                        "MOMO"
                      ]
                    },
                    "rail": {
                      "type": "string",
                      "enum": [
                        "DOMESTIC",
                        "INTERNATIONAL",
                        "LOCAL"
                      ]
                    },
                    "normalized_value": {
                      "type": "string"
                    },
                    "display": {
                      "type": "string"
                    },
                    "country": {
                      "type": "string"
                    },
                    "errors": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Validate any account identifier (RIB, IBAN, LOCAL_BANK, MOMO).\n\n**Tag:** Standards\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/standards/validate/account-identifier\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/standards/validate/account-identifier',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/standards/validate/account-identifier\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/standards/validate/account-identifier',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ]
      }
    },
    "/v1/directory/banks/cm": {
      "get": {
        "tags": [
          "Directory"
        ],
        "summary": "List Cameroon banks with RIB structure and SWIFT codes",
        "operationId": "directoryBanksCm",
        "security": [],
        "responses": {
          "200": {
            "description": "Cameroon bank directory",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "country": {
                      "type": "string"
                    },
                    "banks": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "bank_code": {
                            "type": "string"
                          },
                          "bank_name": {
                            "type": "string"
                          },
                          "swift_bic": {
                            "type": "string"
                          },
                          "supports_rib": {
                            "type": "boolean"
                          }
                        }
                      }
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request — validation failed or malformed input.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          },
          "429": {
            "description": "Too Many Requests — rate limit exceeded.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          }
        },
        "description": "List Cameroon banks with RIB structure and SWIFT codes.\n\n**Tag:** Directory\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/directory/banks/cm\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/directory/banks/cm',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/directory/banks/cm\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/directory/banks/cm',\n]);\n\nprint_r($response->data);"
          }
        ],
        "x-public-endpoint": true,
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ]
      }
    },
    "/v1/kyc/submit": {
      "post": {
        "tags": [
          "KYC & Compliance"
        ],
        "summary": "Submit KYC documents",
        "operationId": "kycSubmit",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "document_type",
                  "document_number",
                  "date_of_birth",
                  "nationality"
                ],
                "properties": {
                  "document_type": {
                    "type": "string",
                    "enum": [
                      "national_id",
                      "passport",
                      "drivers_license"
                    ]
                  },
                  "document_number": {
                    "type": "string"
                  },
                  "document_front_url": {
                    "type": "string"
                  },
                  "document_back_url": {
                    "type": "string"
                  },
                  "selfie_url": {
                    "type": "string",
                    "format": "uri",
                    "description": "URL of the selfie image captured during liveness check. Required for Tier 2 and above CDD."
                  },
                  "liveness_check_token": {
                    "type": "string",
                    "description": "Token returned by the liveness detection provider confirming a real person was captured."
                  },
                  "date_of_birth": {
                    "type": "string",
                    "format": "date",
                    "description": "Customer date of birth in ISO 8601 format. Required for PEP and sanctions screening age correlation.",
                    "example": "1985-06-15"
                  },
                  "nationality": {
                    "type": "string",
                    "maxLength": 2,
                    "description": "ISO 3166-1 alpha-2 nationality code. Required for jurisdictional risk assessment.",
                    "example": "CM"
                  },
                  "tax_identification_number": {
                    "type": "string",
                    "description": "Customer Tax Identification Number (TIN / NIU in Cameroon). Required under COBAC CDD obligations.",
                    "example": "P123456789"
                  },
                  "address_proof_url": {
                    "type": "string",
                    "format": "uri",
                    "description": "URL of supporting address verification document (utility bill, bank statement, etc.)."
                  },
                  "residential_address": {
                    "type": "object",
                    "description": "Customer's current residential address",
                    "properties": {
                      "street_line1": {
                        "type": "string"
                      },
                      "street_line2": {
                        "type": "string"
                      },
                      "city": {
                        "type": "string"
                      },
                      "region": {
                        "type": "string"
                      },
                      "postal_code": {
                        "type": "string"
                      },
                      "country": {
                        "type": "string",
                        "maxLength": 2,
                        "description": "ISO 3166-1 alpha-2 country code"
                      }
                    },
                    "required": [
                      "street_line1",
                      "city",
                      "country"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "KYC submitted",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Submit KYC documents.\n\n**Tag:** KYC & Compliance\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/kyc/submit\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/kyc/submit',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/kyc/submit\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/kyc/submit',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/kyc/sanctions-screen": {
      "post": {
        "tags": [
          "KYC & Compliance"
        ],
        "summary": "Sanctions screening",
        "operationId": "sanctionsScreen",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "full_name"
                ],
                "properties": {
                  "full_name": {
                    "type": "string"
                  },
                  "date_of_birth": {
                    "type": "string",
                    "format": "date"
                  },
                  "nationality": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Screening result",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "match_found": {
                      "type": "boolean"
                    },
                    "matches": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    },
                    "screened_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Sanctions screening.\n\n**Tag:** KYC & Compliance\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/kyc/sanctions-screen\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/kyc/sanctions-screen',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/kyc/sanctions-screen\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/kyc/sanctions-screen',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ]
      }
    },
    "/v1/kyc/data-export": {
      "get": {
        "tags": [
          "KYC & Compliance"
        ],
        "summary": "Export personal data (GDPR)",
        "operationId": "dataExport",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "User data export",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "user": {
                      "type": "object"
                    },
                    "accounts": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    },
                    "transactions": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/PageParam"
          },
          {
            "$ref": "#/components/parameters/LimitParam"
          },
          {
            "$ref": "#/components/parameters/CursorParam"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "description": "Export personal data (GDPR).\n\n**Tag:** KYC & Compliance\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/kyc/data-export\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/kyc/data-export',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/kyc/data-export\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/kyc/data-export',\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/webhooks": {
      "post": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Register webhook",
        "operationId": "webhookRegister",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "url",
                  "events"
                ],
                "properties": {
                  "url": {
                    "type": "string",
                    "format": "uri"
                  },
                  "events": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "wildcard.*",
                        "charge.created",
                        "charge.captured",
                        "charge.voided",
                        "charge.failed",
                        "charge.cancelled",
                        "refund.created",
                        "refund.processed",
                        "refund.failed",
                        "payout.created",
                        "payout.processing",
                        "payout.completed",
                        "payout.failed",
                        "payment.initiated",
                        "payment.authorised",
                        "payment.submitted",
                        "payment.completed",
                        "payment.rejected",
                        "payment.cancelled",
                        "dispute.created",
                        "dispute.evidence_required",
                        "dispute.resolved",
                        "settlement.created",
                        "settlement.processed",
                        "consent.authorised",
                        "consent.revoked",
                        "consent.expired",
                        "loan.applied",
                        "loan.approved",
                        "loan.disbursed",
                        "loan.repaid",
                        "loan.defaulted",
                        "kyc.submitted",
                        "kyc.approved",
                        "kyc.rejected",
                        "mobile_money.charge_initiated",
                        "mobile_money.charge_completed",
                        "mobile_money.charge_failed",
                        "escrow.funded",
                        "escrow.released",
                        "escrow.refunded",
                        "virtual_account.credited",
                        "interbank.payment_submitted",
                        "interbank.payment_completed",
                        "interbank.payment_returned",
                        "pay_by_bank.intent_authorised",
                        "pay_by_bank.intent_rejected",
                        "pay_by_bank.payment_completed",
                        "subscription.created",
                        "subscription.renewed",
                        "subscription.cancelled",
                        "subscription.payment_failed"
                      ]
                    },
                    "description": "List of event types to subscribe to. Use 'wildcard.*' to subscribe to all events.",
                    "minItems": 1,
                    "example": [
                      "charge.created",
                      "charge.captured",
                      "refund.created"
                    ]
                  },
                  "secret": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Webhook registered",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Webhook"
                },
                "examples": {
                  "default": {
                    "summary": "Successful response envelope",
                    "value": {
                      "webhook_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                      "url": "https://api.kangopenbanking.com/v1/resource/3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                      "events": [
                        {
                          "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "event": "charge.created",
                          "created_at": "2025-03-27T14:32:00Z",
                          "api_version": "4.6.0",
                          "data": {},
                          "type": "type_value",
                          "version": "version_value"
                        }
                      ],
                      "is_active": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "**Deprecated.** Use Webhooks v2 (`/v1/webhooks/v2/endpoints`). Sunset: 2026-12-31.\n\nRegister webhook.\n\n**Tag:** Webhooks\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.\n\n**Migration:** Replace with `webhookV2Create`. Move the endpoint to Webhooks v2 and verify the timestamped `X-Webhook-Signature` described in the webhook definitions.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/webhooks\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/webhooks',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/webhooks\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/webhooks',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ],
        "deprecated": true,
        "x-sunset-date": "2026-12-31",
        "x-successor": "/v1/webhooks/v2/endpoints",
        "x-replacement-operation-ids": [
          "webhookV2Create"
        ],
        "x-migration-guide": "Move the endpoint to Webhooks v2 and verify the timestamped `X-Webhook-Signature` described in the webhook definitions."
      },
      "get": {
        "tags": [
          "Webhooks"
        ],
        "summary": "List webhooks",
        "operationId": "webhookList",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Webhooks list",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/Webhook"
                          }
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Cursor-paginated list",
                    "value": {
                      "data": [
                        {
                          "webhook_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "url": "https://api.kangopenbanking.com/v1/resource/3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "events": [
                            {
                              "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                              "event": "charge.created",
                              "created_at": "2025-03-27T14:32:00Z",
                              "api_version": "4.6.0",
                              "data": {},
                              "type": "type_value",
                              "version": "version_value"
                            }
                          ],
                          "is_active": true
                        }
                      ],
                      "pagination": {
                        "page": 1,
                        "limit": 20,
                        "total": 150,
                        "has_next": true
                      },
                      "meta": {
                        "request_id": "550e8400-e29b-41d4-a716-446655440000",
                        "timestamp": "2025-03-27T12:00:00Z"
                      }
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/PageParam"
          },
          {
            "$ref": "#/components/parameters/LimitParam"
          },
          {
            "$ref": "#/components/parameters/CursorParam"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "description": "**Deprecated.** Use Webhooks v2 (`/v1/webhooks/v2/endpoints`). Sunset: 2026-12-31.\n\nList webhooks.\n\n**Tag:** Webhooks\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.\n\n**Migration:** Replace with `webhookV2List`. Move the endpoint to Webhooks v2 and verify the timestamped `X-Webhook-Signature` described in the webhook definitions.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/webhooks\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/webhooks',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/webhooks\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/webhooks',\n]);\n\nprint_r($response->data);"
          }
        ],
        "deprecated": true,
        "x-sunset-date": "2026-12-31",
        "x-successor": "/v1/webhooks/v2/endpoints",
        "x-replacement-operation-ids": [
          "webhookV2List"
        ],
        "x-migration-guide": "Move the endpoint to Webhooks v2 and verify the timestamped `X-Webhook-Signature` described in the webhook definitions."
      }
    },
    "/v1/webhooks/{webhookId}/deliveries": {
      "get": {
        "tags": [
          "Webhooks"
        ],
        "summary": "List webhook deliveries",
        "operationId": "webhookDeliveries",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "webhookId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 25,
              "maximum": 100
            },
            "description": "Items per page"
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 0
            },
            "description": "Items to skip"
          },
          {
            "name": "sort_by",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "created_at"
            },
            "description": "Sort field"
          },
          {
            "name": "sort_order",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "asc",
                "desc"
              ],
              "default": "desc"
            },
            "description": "Sort direction"
          },
          {
            "$ref": "#/components/parameters/StartingAfter"
          },
          {
            "$ref": "#/components/parameters/EndingBefore"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Delivery history",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {}
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Cursor-paginated list",
                    "value": {
                      "data": [
                        "data_value",
                        "data_value"
                      ],
                      "pagination": {
                        "page": 1,
                        "limit": 20,
                        "total": 150,
                        "has_next": true,
                        "has_more": true,
                        "next_cursor": "cursor_01HZX9TRJ4M7YQK6P3W2VBDN5M",
                        "prev_cursor": null,
                        "total_count": 247
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "**Deprecated.** Use Webhooks v2 (`/v1/webhooks/v2/endpoints`). Sunset: 2026-12-31.\n\nList webhook deliveries.\n\n**Tag:** Webhooks\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.\n\n**Migration:** Replace with `webhookV2List`. Move the endpoint to Webhooks v2 and verify the timestamped `X-Webhook-Signature` described in the webhook definitions.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/webhooks/{webhookId}/deliveries\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/webhooks/{webhookId}/deliveries',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/webhooks/{webhookId}/deliveries\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/webhooks/{webhookId}/deliveries',\n]);\n\nprint_r($response->data);"
          }
        ],
        "deprecated": true,
        "x-sunset-date": "2026-12-31",
        "x-successor": "/v1/webhooks/v2/endpoints",
        "x-replacement-operation-ids": [
          "webhookV2List"
        ],
        "x-migration-guide": "Move the endpoint to Webhooks v2 and verify the timestamped `X-Webhook-Signature` described in the webhook definitions."
      }
    },
    "/v1/admin/users": {
      "post": {
        "tags": [
          "Admin"
        ],
        "summary": "Create user",
        "operationId": "adminCreateUser",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "email",
                  "role"
                ],
                "properties": {
                  "email": {
                    "type": "string"
                  },
                  "role": {
                    "type": "string",
                    "enum": [
                      "admin",
                      "institution",
                      "tpp",
                      "personal"
                    ]
                  },
                  "full_name": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "User created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "email": {
                      "type": "string"
                    },
                    "role": {
                      "type": "string"
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Create user.\n\n**Tag:** Admin\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/admin/users\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/admin/users',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/admin/users\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/admin/users',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/admin/clients": {
      "post": {
        "tags": [
          "Admin"
        ],
        "summary": "Create API client",
        "operationId": "adminCreateClient",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "client_name"
                ],
                "properties": {
                  "client_name": {
                    "type": "string"
                  },
                  "scopes": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Client created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "client_id": {
                      "type": "string"
                    },
                    "client_secret": {
                      "type": "string",
                      "description": "Shown once"
                    },
                    "client_name": {
                      "type": "string"
                    },
                    "scopes": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Create API client.\n\n**Tag:** Admin\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/admin/clients\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/admin/clients',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/admin/clients\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/admin/clients',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/admin/metrics": {
      "get": {
        "tags": [
          "Admin"
        ],
        "summary": "Platform metrics",
        "operationId": "adminMetrics",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Metrics dashboard data",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "total_users": {
                      "type": "integer"
                    },
                    "total_transactions": {
                      "type": "integer"
                    },
                    "total_volume": {
                      "type": "number",
                      "deprecated": true,
                      "x-successor": "total_volume_money",
                      "x-sunset": "5.0.0",
                      "description": "Deprecated: floating-point monetary value (IEEE-754 binary64 cannot represent decimal minor units exactly). Use `total_volume_money` instead. Removal is scheduled for v5.0.0."
                    },
                    "total_volume_money": {
                      "$ref": "#/components/schemas/Money",
                      "description": "Canonical string-encoded successor to `total_volume`. Amount and ISO 4217 currency travel together (ISO 20022 ActiveCurrencyAndAmount). Prefer this field: it is exact for zero-decimal currencies (XAF, XOF) and immune to IEEE-754 drift.",
                      "x-added-in": "4.54.0"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/PaginatedList"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Platform metrics.\n\n**Tag:** Admin\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/admin/metrics\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/admin/metrics',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/admin/metrics\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/admin/metrics',\n]);\n\nprint_r($response->data);"
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          },
          {
            "$ref": "#/components/parameters/LimitParam"
          },
          {
            "$ref": "#/components/parameters/CursorParam"
          }
        ]
      }
    },
    "/v1/admin/sandbox/accounts": {
      "get": {
        "tags": [
          "Admin"
        ],
        "summary": "List sandbox accounts",
        "operationId": "adminSandboxAccounts",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Sandbox accounts",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/Account"
                          }
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Cursor-paginated list",
                    "value": {
                      "data": [
                        {
                          "account_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "account_type": "checking",
                          "account_subtype": "personal_current",
                          "currency": "XAF",
                          "identification_scheme": "LOCAL_BANK",
                          "identification_value": "identification_value_value",
                          "status": "active",
                          "id": "obj_01HZX9TRJ4M7YQK6P3W2VBDN5K",
                          "object": "resource",
                          "created_at": "2026-05-02T10:15:30Z"
                        },
                        {
                          "account_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "account_type": "checking",
                          "account_subtype": "personal_current",
                          "currency": "XAF",
                          "identification_scheme": "LOCAL_BANK",
                          "identification_value": "identification_value_value",
                          "status": "active",
                          "id": "obj_01HZX9TRJ4M7YQK6P3W2VBDN5L",
                          "object": "resource",
                          "created_at": "2026-05-02T10:15:31Z"
                        }
                      ],
                      "pagination": {
                        "page": 1,
                        "limit": 20,
                        "total": 150,
                        "has_next": true,
                        "has_more": true,
                        "next_cursor": "cursor_01HZX9TRJ4M7YQK6P3W2VBDN5M",
                        "prev_cursor": null,
                        "total_count": 247
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/PageParam"
          },
          {
            "$ref": "#/components/parameters/LimitParam"
          },
          {
            "$ref": "#/components/parameters/CursorParam"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "description": "List sandbox accounts.\n\n**Tag:** Admin\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/admin/sandbox/accounts\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/admin/sandbox/accounts',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/admin/sandbox/accounts\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/admin/sandbox/accounts',\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/admin/system-config": {
      "get": {
        "tags": [
          "Admin"
        ],
        "summary": "Get system configuration",
        "operationId": "adminSystemConfig",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "System config",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Get system configuration.\n\n**Tag:** Admin\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/admin/system-config\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/admin/system-config',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/admin/system-config\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/admin/system-config',\n]);\n\nprint_r($response->data);"
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ]
      },
      "put": {
        "tags": [
          "Admin"
        ],
        "summary": "Update system configuration",
        "operationId": "adminSystemConfigUpdate",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "System configuration updated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Update system configuration.\n\n**Tag:** Admin\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X PUT \"https://api.kangopenbanking.com/v1/admin/system-config\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'PUT',\n  path: '/v1/admin/system-config',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"PUT\",\n    path=\"/v1/admin/system-config\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'PUT',\n    'path'   => '/v1/admin/system-config',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ]
      }
    },
    "/v1/admin/webhooks": {
      "get": {
        "tags": [
          "Admin"
        ],
        "summary": "List all webhooks (admin)",
        "operationId": "adminWebhooks",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "sort_by",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "created_at"
            },
            "description": "Sort field"
          },
          {
            "name": "sort_order",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "asc",
                "desc"
              ],
              "default": "desc"
            },
            "description": "Sort direction"
          },
          {
            "$ref": "#/components/parameters/PageParam"
          },
          {
            "$ref": "#/components/parameters/LimitParam"
          },
          {
            "$ref": "#/components/parameters/CursorParam"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "All webhooks",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/Webhook"
                          }
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Cursor-paginated list",
                    "value": {
                      "data": [
                        {
                          "webhook_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "url": "https://api.kangopenbanking.com/v1/resource/3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "events": [
                            {
                              "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                              "event": "charge.created",
                              "created_at": "2025-03-27T14:32:00Z",
                              "api_version": "4.6.0",
                              "data": {},
                              "type": "type_value",
                              "version": "version_value"
                            }
                          ],
                          "is_active": true
                        }
                      ],
                      "pagination": {
                        "page": 1,
                        "limit": 20,
                        "total": 150,
                        "has_next": true
                      },
                      "meta": {
                        "request_id": "550e8400-e29b-41d4-a716-446655440000",
                        "timestamp": "2025-03-27T12:00:00Z"
                      }
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "List all webhooks (admin).\n\n**Tag:** Admin\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/admin/webhooks\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/admin/webhooks',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/admin/webhooks\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/admin/webhooks',\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/admin/transactions/review": {
      "get": {
        "tags": [
          "Admin"
        ],
        "summary": "Review transactions",
        "operationId": "adminTransactionReview",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "sort_by",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "created_at"
            },
            "description": "Sort field"
          },
          {
            "name": "sort_order",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "asc",
                "desc"
              ],
              "default": "desc"
            },
            "description": "Sort direction"
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/PageParam"
          },
          {
            "$ref": "#/components/parameters/LimitParam"
          },
          {
            "$ref": "#/components/parameters/CursorParam"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Transactions for review",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/Transaction"
                          }
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Successful response envelope",
                    "value": {
                      "data": [
                        {
                          "transaction_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "amount": "25000",
                          "currency": "XAF",
                          "type": "debit",
                          "timestamp": "2026-05-02T10:15:30Z"
                        }
                      ],
                      "pagination": {
                        "page": 1,
                        "limit": 20,
                        "total": 150,
                        "has_next": true
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Review transactions.\n\n**Tag:** Admin\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/admin/transactions/review\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/admin/transactions/review',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/admin/transactions/review\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/admin/transactions/review',\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/admin/loans": {
      "get": {
        "tags": [
          "Admin"
        ],
        "summary": "List all loans (admin)",
        "operationId": "adminListLoans",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "sort_by",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "created_at"
            },
            "description": "Sort field"
          },
          {
            "name": "sort_order",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "asc",
                "desc"
              ],
              "default": "desc"
            },
            "description": "Sort direction"
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "user_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "product_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/PageParam"
          },
          {
            "$ref": "#/components/parameters/LimitParam"
          },
          {
            "$ref": "#/components/parameters/CursorParam"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Loan applications with accounts",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/LoanApplication"
                          }
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Cursor-paginated list",
                    "value": {
                      "data": [
                        {
                          "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "product_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "amount": "1000000",
                          "currency": "XAF",
                          "term_months": 12,
                          "status": "applied",
                          "object": "resource",
                          "created_at": "2026-05-02T10:15:30Z"
                        },
                        {
                          "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "product_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "amount": "1000000",
                          "currency": "XAF",
                          "term_months": 12,
                          "status": "applied",
                          "object": "resource",
                          "created_at": "2026-05-02T10:15:31Z"
                        }
                      ],
                      "pagination": {
                        "page": 1,
                        "limit": 20,
                        "total": 150,
                        "has_next": true,
                        "has_more": true,
                        "next_cursor": "cursor_01HZX9TRJ4M7YQK6P3W2VBDN5M",
                        "prev_cursor": null,
                        "total_count": 247
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "List all loans (admin).\n\n**Tag:** Admin\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/admin/loans\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/admin/loans',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/admin/loans\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/admin/loans',\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/admin/savings": {
      "get": {
        "tags": [
          "Admin"
        ],
        "summary": "List all savings accounts (admin)",
        "operationId": "adminListSavings",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "sort_by",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "created_at"
            },
            "description": "Sort field"
          },
          {
            "name": "sort_order",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "asc",
                "desc"
              ],
              "default": "desc"
            },
            "description": "Sort direction"
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "user_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "product_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "account_type",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/PageParam"
          },
          {
            "$ref": "#/components/parameters/LimitParam"
          },
          {
            "$ref": "#/components/parameters/CursorParam"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Savings accounts with products",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/SavingsAccount"
                          }
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Cursor-paginated list",
                    "value": {
                      "data": [
                        {
                          "account_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "balance": "5000",
                          "currency": "XAF",
                          "status": "active",
                          "id": "obj_01HZX9TRJ4M7YQK6P3W2VBDN5K",
                          "object": "resource",
                          "created_at": "2026-05-02T10:15:30Z"
                        },
                        {
                          "account_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "balance": "5000",
                          "currency": "XAF",
                          "status": "active",
                          "id": "obj_01HZX9TRJ4M7YQK6P3W2VBDN5L",
                          "object": "resource",
                          "created_at": "2026-05-02T10:15:31Z"
                        }
                      ],
                      "pagination": {
                        "page": 1,
                        "limit": 20,
                        "total": 150,
                        "has_next": true,
                        "has_more": true,
                        "next_cursor": "cursor_01HZX9TRJ4M7YQK6P3W2VBDN5M",
                        "prev_cursor": null,
                        "total_count": 247
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "List all savings accounts (admin).\n\n**Tag:** Admin\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/admin/savings\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/admin/savings',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/admin/savings\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/admin/savings',\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/admin/consents": {
      "get": {
        "tags": [
          "Admin"
        ],
        "summary": "List all consents (admin)",
        "operationId": "adminListConsents",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "sort_by",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "created_at"
            },
            "description": "Sort field"
          },
          {
            "name": "sort_order",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "asc",
                "desc"
              ],
              "default": "desc"
            },
            "description": "Sort direction"
          },
          {
            "name": "type",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "aisp",
                "pisp"
              ],
              "default": "aisp"
            }
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "user_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "client_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/PageParam"
          },
          {
            "$ref": "#/components/parameters/LimitParam"
          },
          {
            "$ref": "#/components/parameters/CursorParam"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "AISP or PISP consents",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/Consent"
                          }
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Cursor-paginated list",
                    "value": {
                      "data": [
                        {
                          "consent_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "status": "AwaitingAuthorisation",
                          "permissions": [
                            "permissions_value"
                          ],
                          "expiration_date": "2026-05-02T10:15:30Z",
                          "created_at": "2026-05-02T10:15:30Z",
                          "id": "obj_01HZX9TRJ4M7YQK6P3W2VBDN5K",
                          "object": "resource"
                        },
                        {
                          "consent_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "status": "AwaitingAuthorisation",
                          "permissions": [
                            "permissions_value"
                          ],
                          "expiration_date": "2026-05-02T10:15:30Z",
                          "created_at": "2026-05-02T10:15:31Z",
                          "id": "obj_01HZX9TRJ4M7YQK6P3W2VBDN5L",
                          "object": "resource"
                        }
                      ],
                      "pagination": {
                        "page": 1,
                        "limit": 20,
                        "total": 150,
                        "has_next": true,
                        "has_more": true,
                        "next_cursor": "cursor_01HZX9TRJ4M7YQK6P3W2VBDN5M",
                        "prev_cursor": null,
                        "total_count": 247
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "List all consents (admin).\n\n**Tag:** Admin\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/admin/consents\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/admin/consents',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/admin/consents\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/admin/consents',\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/admin/staff/assign": {
      "post": {
        "tags": [
          "Admin"
        ],
        "summary": "Assign staff to branch",
        "operationId": "adminAssignStaff",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "user_id",
                  "branch_id",
                  "role"
                ],
                "properties": {
                  "user_id": {
                    "type": "string"
                  },
                  "branch_id": {
                    "type": "string"
                  },
                  "role": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Staff assigned to branch",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Assign staff to branch.\n\n**Tag:** Admin\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/admin/staff/assign\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/admin/staff/assign',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/admin/staff/assign\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/admin/staff/assign',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ]
      }
    },
    "/v1/admin/branches": {
      "get": {
        "tags": [
          "Admin"
        ],
        "summary": "List branches",
        "operationId": "adminManageBranches",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Branches list",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {}
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Cursor-paginated list",
                    "value": {
                      "data": [
                        "data_value",
                        "data_value"
                      ],
                      "pagination": {
                        "page": 1,
                        "limit": 20,
                        "total": 150,
                        "has_next": true,
                        "has_more": true,
                        "next_cursor": "cursor_01HZX9TRJ4M7YQK6P3W2VBDN5M",
                        "prev_cursor": null,
                        "total_count": 247
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/PageParam"
          },
          {
            "$ref": "#/components/parameters/LimitParam"
          },
          {
            "$ref": "#/components/parameters/CursorParam"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "description": "List branches.\n\n**Tag:** Admin\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/admin/branches\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/admin/branches',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/admin/branches\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/admin/branches',\n]);\n\nprint_r($response->data);"
          }
        ]
      },
      "post": {
        "tags": [
          "Admin"
        ],
        "summary": "Create branch",
        "operationId": "adminCreateBranch",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Branch created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "name": {
                      "type": "string"
                    },
                    "city": {
                      "type": "string"
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Create branch.\n\n**Tag:** Admin\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/admin/branches\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/admin/branches',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/admin/branches\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/admin/branches',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/communications/send": {
      "post": {
        "tags": [
          "Communications"
        ],
        "summary": "Send communication",
        "operationId": "sendCommunication",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "type",
                  "recipient",
                  "body"
                ],
                "properties": {
                  "type": {
                    "type": "string",
                    "enum": [
                      "email",
                      "sms",
                      "push"
                    ]
                  },
                  "recipient": {
                    "type": "string"
                  },
                  "subject": {
                    "type": "string"
                  },
                  "body": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Communication sent",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Send communication.\n\n**Tag:** Communications\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/communications/send\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/communications/send',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/communications/send\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/communications/send',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/communications/bulk": {
      "post": {
        "tags": [
          "Communications"
        ],
        "summary": "Send bulk communication",
        "operationId": "sendBulkCommunication",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Bulk communication queued",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "queued": {
                      "type": "integer"
                    },
                    "batch_id": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string",
                      "example": "queued"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Send bulk communication.\n\n**Tag:** Communications\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/communications/bulk\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/communications/bulk',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/communications/bulk\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/communications/bulk',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/invoices/generate": {
      "post": {
        "tags": [
          "Settlement"
        ],
        "summary": "Generate invoice",
        "operationId": "generateInvoice",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Invoice generated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "invoice_number": {
                      "type": "string"
                    },
                    "amount": {
                      "type": "string",
                      "pattern": "^[0-9]{1,15}$",
                      "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits). Must be consistent with the currency field."
                    },
                    "currency": {
                      "type": "string",
                      "enum": [
                        "XAF",
                        "XOF",
                        "USD",
                        "EUR",
                        "GBP",
                        "CNY",
                        "NGN",
                        "GHS",
                        "KES",
                        "ZAR"
                      ],
                      "default": "XAF",
                      "description": "ISO 4217 currency code. Default is XAF (Central African CFA Franc)."
                    },
                    "status": {
                      "type": "string"
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Generate invoice.\n\n**Tag:** Settlement\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/invoices/generate\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/invoices/generate',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/invoices/generate\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/invoices/generate',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/institutions/register": {
      "post": {
        "tags": [
          "Institution"
        ],
        "summary": "Register institution",
        "operationId": "institutionRegister",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Institution registered",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "name": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string"
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Register institution.\n\n**Tag:** Institution\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/institutions/register\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/institutions/register',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/institutions/register\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/institutions/register',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/institutions/{institutionId}/clients": {
      "post": {
        "tags": [
          "Institution"
        ],
        "summary": "Create institution API client",
        "operationId": "institutionCreateClient",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "institutionId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Client created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "client_id": {
                      "type": "string"
                    },
                    "client_secret": {
                      "type": "string",
                      "description": "Shown once"
                    },
                    "scopes": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Create institution API client.\n\n**Tag:** Institution\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/institutions/{institutionId}/clients\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/institutions/{institutionId}/clients',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/institutions/{institutionId}/clients\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/institutions/{institutionId}/clients',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/institutions/{institutionId}/kyb": {
      "post": {
        "tags": [
          "Institution"
        ],
        "summary": "Submit business KYC",
        "operationId": "businessKycSubmit",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "institutionId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "KYB submitted",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "submission_id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "status": {
                      "type": "string",
                      "example": "pending_review"
                    },
                    "submitted_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Submit business KYC.\n\n**Tag:** Institution\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/institutions/{institutionId}/kyb\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/institutions/{institutionId}/kyb',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/institutions/{institutionId}/kyb\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/institutions/{institutionId}/kyb',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/crediq/health-check": {
      "get": {
        "tags": [
          "CrediQ"
        ],
        "summary": "CrediQ health check",
        "operationId": "crediqHealthCheck",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Health status",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "CrediQ health check.\n\n**Tag:** CrediQ\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/crediq/health-check\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/crediq/health-check',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/crediq/health-check\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/crediq/health-check',\n]);\n\nprint_r($response->data);"
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ]
      }
    },
    "/v1/crediq/baseline-score": {
      "post": {
        "tags": [
          "CrediQ"
        ],
        "summary": "Generate baseline score",
        "operationId": "crediqBaselineScore",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Baseline score",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreditScore"
                },
                "examples": {
                  "default": {
                    "summary": "Successful response envelope",
                    "value": {
                      "score": 680,
                      "grade": "A",
                      "calculated_at": "2026-05-02T10:15:30Z",
                      "success": true,
                      "data": {
                        "id": "obj_01HZX9TRJ4M7YQK6P3W2VBDN5K",
                        "object": "resource",
                        "created_at": "2026-05-02T10:15:30Z"
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      }
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Generate baseline score.\n\n**Tag:** CrediQ\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/crediq/baseline-score\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/crediq/baseline-score',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/crediq/baseline-score\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/crediq/baseline-score',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ]
      }
    },
    "/v1/crediq/health-metrics": {
      "post": {
        "tags": [
          "CrediQ"
        ],
        "summary": "Calculate health metrics",
        "operationId": "crediqHealthMetrics",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Health metrics",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Calculate health metrics.\n\n**Tag:** CrediQ\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/crediq/health-metrics\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/crediq/health-metrics',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/crediq/health-metrics\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/crediq/health-metrics',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ]
      }
    },
    "/v1/crediq/action-plan": {
      "post": {
        "tags": [
          "CrediQ"
        ],
        "summary": "Generate action plan",
        "operationId": "crediqActionPlan",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Action plan",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Generate action plan.\n\n**Tag:** CrediQ\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/crediq/action-plan\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/crediq/action-plan',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/crediq/action-plan\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/crediq/action-plan',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ]
      }
    },
    "/v1/postiq/codes": {
      "post": {
        "tags": [
          "PostiQ"
        ],
        "summary": "Create PostiQ code",
        "operationId": "postiqCreateCode",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "latitude",
                  "longitude"
                ],
                "properties": {
                  "latitude": {
                    "type": "number",
                    "minimum": -90,
                    "maximum": 90
                  },
                  "longitude": {
                    "type": "number",
                    "minimum": -180,
                    "maximum": 180
                  },
                  "area_name": {
                    "type": "string",
                    "maxLength": 255
                  },
                  "road_name": {
                    "type": "string",
                    "maxLength": 255
                  },
                  "house_number": {
                    "type": "integer",
                    "minimum": 1
                  }
                }
              },
              "example": {
                "latitude": 3.8667,
                "longitude": 11.5167,
                "area_name": "Bastos"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Code created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "postiq_code": {
                      "type": "string"
                    },
                    "full_address": {
                      "type": "string"
                    },
                    "verified_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Creates a PostiQ code from GPS coordinates in Cameroon and records it as the signed-in customer's verified address. Requires a customer access token.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/postiq/codes\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"latitude\":3.8667,\"longitude\":11.5167,\"area_name\":\"Bastos\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/postiq/codes',\n  body: { latitude: 3.8667, longitude: 11.5167, area_name: 'Bastos' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/postiq/codes\",\n    body={\"latitude\": 3.8667, \"longitude\": 11.5167, \"area_name\": \"Bastos\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/postiq/codes',\n    'body'   => ['latitude' => 3.8667, 'longitude' => 11.5167, 'area_name' => 'Bastos'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/postiq/codes/{code}": {
      "get": {
        "tags": [
          "PostiQ"
        ],
        "summary": "Lookup PostiQ code",
        "operationId": "postiqLookupCode",
        "security": [],
        "parameters": [
          {
            "name": "code",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z]{2}[0-9]{2}[ +%20]?[0-9]{3}$"
            },
            "example": "YA10 382"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Address details",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "postiq_code": {
                      "type": "string"
                    },
                    "full_address": {
                      "type": "string"
                    },
                    "city": {
                      "type": "string"
                    },
                    "country": {
                      "type": "string"
                    },
                    "region": {
                      "type": "string"
                    },
                    "latitude": {
                      "type": "number"
                    },
                    "longitude": {
                      "type": "number"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Resolves a PostiQ code (format AA## ###, for example YA10 382) to its address. No sign-in required; nothing is stored.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/postiq/codes/YA10%20382\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/postiq/codes/YA10%20382',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/postiq/codes/YA10%20382\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/postiq/codes/YA10%20382',\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/woocommerce/merchants": {
      "post": {
        "tags": [
          "WooCommerce"
        ],
        "summary": "Register WooCommerce merchant",
        "description": "Register a WooCommerce store for Kang Open Banking payment processing. Returns API credentials.",
        "operationId": "woocommerceRegisterMerchant",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "store_name",
                  "store_url",
                  "admin_email"
                ],
                "properties": {
                  "store_name": {
                    "type": "string",
                    "example": "My Cameroon Store"
                  },
                  "store_url": {
                    "type": "string",
                    "format": "uri",
                    "example": "https://mystore.cm"
                  },
                  "admin_email": {
                    "type": "string",
                    "format": "email"
                  },
                  "plugin_version": {
                    "type": "string",
                    "example": "1.0.0"
                  },
                  "business_type": {
                    "type": "string",
                    "enum": [
                      "individual",
                      "company"
                    ]
                  },
                  "phone": {
                    "type": "string"
                  },
                  "country": {
                    "type": "string",
                    "default": "CM"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Merchant registered",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WooCommerceMerchant"
                },
                "examples": {
                  "default": {
                    "summary": "Successful response envelope",
                    "value": {
                      "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                      "store_name": "store_name_value",
                      "store_url": "https://api.kangopenbanking.com/v1/resource/3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                      "admin_email": "developer@kangopenbanking.com",
                      "success": true,
                      "data": {
                        "id": "obj_01HZX9TRJ4M7YQK6P3W2VBDN5K",
                        "object": "resource",
                        "created_at": "2026-05-02T10:15:30Z"
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      }
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/woocommerce/merchants\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/woocommerce/merchants',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/woocommerce/merchants\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/woocommerce/merchants',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/woocommerce/validate-install": {
      "post": {
        "tags": [
          "WooCommerce"
        ],
        "summary": "Validate WooCommerce plugin installation",
        "description": "Validate WooCommerce plugin installation.\n\n**Tag:** WooCommerce\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "operationId": "woocommerceValidateInstall",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "api_key",
                  "store_url"
                ],
                "properties": {
                  "api_key": {
                    "type": "string"
                  },
                  "plugin_version": {
                    "type": "string"
                  },
                  "store_url": {
                    "type": "string",
                    "format": "uri"
                  },
                  "php_version": {
                    "type": "string"
                  },
                  "wp_version": {
                    "type": "string"
                  },
                  "wc_version": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Validation result",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "valid": {
                      "type": "boolean"
                    },
                    "merchant_id": {
                      "type": "string"
                    },
                    "store_name": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "active",
                        "inactive",
                        "suspended"
                      ]
                    },
                    "features": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/woocommerce/validate-install\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/woocommerce/validate-install',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/woocommerce/validate-install\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/woocommerce/validate-install',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ]
      }
    },
    "/v1/woocommerce/plugin/download": {
      "get": {
        "tags": [
          "WooCommerce"
        ],
        "summary": "Download WooCommerce plugin ZIP",
        "description": "Downloads the complete Woo for Kang WordPress plugin as a ZIP file ready for installation. Authentication required. A developer account or merchant account bearer token must be provided.",
        "operationId": "woocommerceDownloadPlugin",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Plugin ZIP file",
            "content": {
              "application/zip": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "application/json": {
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/GenericSuccessResponse"
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorised — a valid bearer token is required to download the plugin.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/woocommerce/plugin/download\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/woocommerce/plugin/download',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/woocommerce/plugin/download\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/woocommerce/plugin/download',\n]);\n\nprint_r($response->data);"
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ]
      }
    },
    "/v1/woocommerce/process-payment": {
      "post": {
        "tags": [
          "WooCommerce"
        ],
        "summary": "Process WooCommerce payment",
        "description": "Initiates a payment for a WooCommerce order. Called by the WordPress plugin during checkout.",
        "operationId": "woocommerceProcessPayment",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "amount",
                  "currency",
                  "woocommerce_order_id",
                  "customer_email"
                ],
                "properties": {
                  "amount": {
                    "type": "string",
                    "example": "25000",
                    "pattern": "^[0-9]{1,15}$",
                    "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits). Must be consistent with the currency field."
                  },
                  "currency": {
                    "type": "string",
                    "default": "XAF",
                    "enum": [
                      "XAF",
                      "XOF",
                      "USD",
                      "EUR",
                      "GBP",
                      "CNY",
                      "NGN",
                      "GHS",
                      "KES",
                      "ZAR"
                    ],
                    "description": "ISO 4217 currency code. Default is XAF (Central African CFA Franc)."
                  },
                  "woocommerce_order_id": {
                    "type": "integer",
                    "example": 1234
                  },
                  "customer_email": {
                    "type": "string",
                    "format": "email"
                  },
                  "customer_name": {
                    "type": "string"
                  },
                  "customer_phone": {
                    "type": "string"
                  },
                  "payment_methods": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "mobile_money",
                        "card",
                        "bank_transfer"
                      ]
                    }
                  },
                  "return_url": {
                    "type": "string",
                    "format": "uri"
                  },
                  "cancel_url": {
                    "type": "string",
                    "format": "uri"
                  },
                  "webhook_url": {
                    "type": "string",
                    "format": "uri"
                  },
                  "metadata": {
                    "type": "object"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Payment initiated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "transaction_ref": {
                      "type": "string"
                    },
                    "payment_url": {
                      "type": "string",
                      "format": "uri"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "pending",
                        "processing"
                      ]
                    },
                    "expires_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/PaymentIntentCreated"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/woocommerce/process-payment\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/woocommerce/process-payment',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/woocommerce/process-payment\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/woocommerce/process-payment',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/woocommerce/transactions": {
      "get": {
        "tags": [
          "WooCommerce"
        ],
        "summary": "Sync WooCommerce transactions",
        "description": "Retrieve transaction history for a WooCommerce merchant. Used by the plugin for transaction synchronization.",
        "operationId": "woocommerceListTransactions",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "start_date",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "end_date",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "pending",
                "completed",
                "failed",
                "refunded"
              ]
            }
          },
          {
            "name": "payment_method",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 25,
              "maximum": 100
            },
            "description": "Items per page"
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 0
            },
            "description": "Items to skip"
          },
          {
            "name": "sort_by",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "created_at"
            },
            "description": "Sort field"
          },
          {
            "name": "sort_order",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "asc",
                "desc"
              ],
              "default": "desc"
            },
            "description": "Sort direction"
          },
          {
            "$ref": "#/components/parameters/StartingAfter"
          },
          {
            "$ref": "#/components/parameters/EndingBefore"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Transaction list",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/WooCommerceTransaction"
                          }
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Cursor-paginated list",
                    "value": {
                      "data": [
                        {
                          "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "transaction_ref": "transaction_ref_value",
                          "amount": "5000",
                          "currency": "XAF",
                          "status": "pending",
                          "object": "resource",
                          "created_at": "2026-05-02T10:15:30Z"
                        },
                        {
                          "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "transaction_ref": "transaction_ref_value",
                          "amount": "5000",
                          "currency": "XAF",
                          "status": "pending",
                          "object": "resource",
                          "created_at": "2026-05-02T10:15:31Z"
                        }
                      ],
                      "pagination": {
                        "page": 1,
                        "limit": 20,
                        "total": 150,
                        "has_next": true,
                        "has_more": true,
                        "next_cursor": "cursor_01HZX9TRJ4M7YQK6P3W2VBDN5M",
                        "prev_cursor": null,
                        "total_count": 247
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/woocommerce/transactions\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/woocommerce/transactions',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/woocommerce/transactions\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/woocommerce/transactions',\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/woocommerce/webhook": {
      "post": {
        "tags": [
          "WooCommerce"
        ],
        "summary": "WooCommerce payment webhook",
        "description": "Receives payment status updates and updates the corresponding WooCommerce order.",
        "operationId": "woocommercePaymentWebhook",
        "security": [
          {
            "WooCommerceSignature": []
          },
          {
            "WebhookSignature": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "event_type",
                  "transaction_ref",
                  "status"
                ],
                "properties": {
                  "event_type": {
                    "type": "string",
                    "enum": [
                      "payment.completed",
                      "payment.failed",
                      "payment.cancelled",
                      "payment.refunded"
                    ]
                  },
                  "transaction_ref": {
                    "type": "string"
                  },
                  "woocommerce_order_id": {
                    "type": "integer"
                  },
                  "status": {
                    "type": "string",
                    "enum": [
                      "completed",
                      "successful",
                      "failed",
                      "cancelled",
                      "refunded"
                    ]
                  },
                  "amount": {
                    "type": "string",
                    "pattern": "^[0-9]{1,15}$",
                    "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits). Must be consistent with the currency field."
                  },
                  "currency": {
                    "type": "string",
                    "enum": [
                      "XAF",
                      "XOF",
                      "USD",
                      "EUR",
                      "GBP",
                      "CNY",
                      "NGN",
                      "GHS",
                      "KES",
                      "ZAR"
                    ],
                    "default": "XAF",
                    "description": "ISO 4217 currency code. Default is XAF (Central African CFA Franc)."
                  },
                  "payment_method": {
                    "type": "string"
                  },
                  "timestamp": {
                    "type": "string",
                    "format": "date-time"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Webhook processed",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/PaymentIntentCreated"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/woocommerce/webhook\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/woocommerce/webhook',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/woocommerce/webhook\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/woocommerce/webhook',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ]
      }
    },
    "/v1/sandbox/accounts": {
      "post": {
        "tags": [
          "Sandbox"
        ],
        "summary": "Create sandbox account",
        "operationId": "sandboxCreateAccount",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "201": {
            "description": "Sandbox account created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Create sandbox account.\n\n**Tag:** Sandbox\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/sandbox/accounts\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/sandbox/accounts',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/sandbox/accounts\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/sandbox/accounts',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/sandbox/api-keys": {
      "post": {
        "tags": [
          "Sandbox"
        ],
        "summary": "Create sandbox API key",
        "operationId": "sandboxCreateApiKey",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "201": {
            "description": "API key created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "api_key": {
                      "type": "string",
                      "pattern": "^sbx_[0-9a-f]{64}$",
                      "example": "sbx_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
                    },
                    "secret": {
                      "type": "string"
                    },
                    "environment": {
                      "type": "string"
                    },
                    "tier": {
                      "type": "string",
                      "enum": [
                        "free",
                        "pro",
                        "enterprise"
                      ],
                      "default": "free"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Create sandbox API key.\n\n**Tag:** Sandbox\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/sandbox/api-keys\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/sandbox/api-keys',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/sandbox/api-keys\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/sandbox/api-keys',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/sandbox/data/generate": {
      "post": {
        "tags": [
          "Sandbox"
        ],
        "summary": "Generate test data",
        "operationId": "sandboxGenerateData",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Test data generated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Generate test data.\n\n**Tag:** Sandbox\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/sandbox/data/generate\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/sandbox/data/generate',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/sandbox/data/generate\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/sandbox/data/generate',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ]
      }
    },
    "/v1/sandbox/webhooks": {
      "post": {
        "tags": [
          "Sandbox"
        ],
        "summary": "Register sandbox webhook",
        "operationId": "sandboxRegisterWebhook",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "url",
                  "events"
                ],
                "properties": {
                  "url": {
                    "type": "string"
                  },
                  "events": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Webhook registered",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Webhook"
                },
                "examples": {
                  "default": {
                    "summary": "Successful response envelope",
                    "value": {
                      "webhook_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                      "url": "https://api.kangopenbanking.com/v1/resource/3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                      "events": [
                        {
                          "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "event": "charge.created",
                          "created_at": "2025-03-27T14:32:00Z",
                          "api_version": "4.6.0",
                          "data": {},
                          "type": "type_value",
                          "version": "version_value"
                        }
                      ],
                      "is_active": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Register sandbox webhook.\n\n**Tag:** Sandbox\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/sandbox/webhooks\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/sandbox/webhooks',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/sandbox/webhooks\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/sandbox/webhooks',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/developers/register": {
      "post": {
        "tags": [
          "Developer"
        ],
        "summary": "Register developer app",
        "operationId": "developerRegisterApp",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "app_name",
                  "redirect_uris"
                ],
                "properties": {
                  "app_name": {
                    "type": "string"
                  },
                  "redirect_uris": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "use_case": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "App registered",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "client_id": {
                      "type": "string"
                    },
                    "client_secret": {
                      "type": "string",
                      "description": "Shown once"
                    },
                    "app_name": {
                      "type": "string"
                    },
                    "redirect_uris": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Register developer app.\n\n**Tag:** Developer\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/developers/register\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/developers/register',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/developers/register\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/developers/register',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/gateway/charges": {
      "post": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "Create a charge",
        "operationId": "gatewayCreateCharge",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "MerchantSecretKey": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/XFapiInteractionId"
          },
          {
            "$ref": "#/components/parameters/XFapiCustomerIpAddress"
          },
          {
            "$ref": "#/components/parameters/XFapiAuthDate"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "merchant_id",
                  "amount",
                  "channel",
                  "tx_ref"
                ],
                "properties": {
                  "merchant_id": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "amount": {
                    "type": "string",
                    "example": "5000",
                    "pattern": "^[0-9]{1,15}$",
                    "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits). Must be consistent with the currency field."
                  },
                  "currency": {
                    "type": "string",
                    "default": "XAF",
                    "enum": [
                      "XAF",
                      "XOF",
                      "USD",
                      "EUR",
                      "GBP",
                      "CNY",
                      "NGN",
                      "GHS",
                      "KES",
                      "ZAR"
                    ],
                    "description": "ISO 4217 currency code. Default is XAF (Central African CFA Franc)."
                  },
                  "channel": {
                    "type": "string",
                    "enum": [
                      "mobile_money",
                      "card",
                      "bank_transfer",
                      "apple_pay",
                      "google_pay",
                      "ussd",
                      "paypal"
                    ]
                  },
                  "customer_phone": {
                    "type": "string"
                  },
                  "customer_email": {
                    "type": "string"
                  },
                  "tx_ref": {
                    "type": "string"
                  },
                  "metadata": {
                    "type": "object"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Charge created",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/StandardResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/GatewayCharge"
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Successful response envelope",
                    "value": {
                      "data": {
                        "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                        "merchant_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                        "amount": "5000",
                        "currency": "XAF",
                        "channel": "mobile_money",
                        "status": "pending",
                        "created_at": "2026-05-02T10:15:30Z",
                        "object": "resource"
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": " Responses will conform to the StandardResponse envelope in a future minor release.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/gateway/charges\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/gateway/charges',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/gateway/charges\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/gateway/charges',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      },
      "get": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "List charges",
        "operationId": "gatewayListCharges",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "merchant_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "channel",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "from",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "to",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "sort_by",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "created_at"
            },
            "description": "Sort field"
          },
          {
            "name": "sort_order",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "asc",
                "desc"
              ],
              "default": "desc"
            },
            "description": "Sort direction"
          },
          {
            "$ref": "#/components/parameters/PageParam"
          },
          {
            "$ref": "#/components/parameters/LimitParam"
          },
          {
            "$ref": "#/components/parameters/CursorParam"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Charges list",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/GatewayCharge"
                          }
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Cursor-paginated list",
                    "value": {
                      "data": [
                        {
                          "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "merchant_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "amount": "5000",
                          "currency": "XAF",
                          "channel": "mobile_money",
                          "status": "pending",
                          "created_at": "2026-05-02T10:15:30Z",
                          "object": "resource"
                        },
                        {
                          "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "merchant_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "amount": "5000",
                          "currency": "XAF",
                          "channel": "mobile_money",
                          "status": "pending",
                          "created_at": "2026-05-02T10:15:31Z",
                          "object": "resource"
                        }
                      ],
                      "pagination": {
                        "page": 1,
                        "limit": 20,
                        "total": 150,
                        "has_next": true,
                        "has_more": true,
                        "next_cursor": "cursor_01HZX9TRJ4M7YQK6P3W2VBDN5M",
                        "prev_cursor": null,
                        "total_count": 247
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "List charges.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/gateway/charges\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/gateway/charges',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/gateway/charges\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/gateway/charges',\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/gateway/charges/{chargeId}": {
      "get": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "Get charge",
        "operationId": "gatewayGetCharge",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "chargeId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Charge details",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/StandardResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/GatewayCharge"
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Successful response envelope",
                    "value": {
                      "data": {
                        "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                        "merchant_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                        "amount": "5000",
                        "currency": "XAF",
                        "channel": "mobile_money",
                        "status": "pending",
                        "created_at": "2026-05-02T10:15:30Z",
                        "object": "resource"
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Get charge.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/gateway/charges/{chargeId}\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/gateway/charges/{chargeId}',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/gateway/charges/{chargeId}\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/gateway/charges/{chargeId}',\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/gateway/charges/{chargeId}/verify": {
      "post": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "Verify charge with provider",
        "operationId": "gatewayVerifyCharge",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "chargeId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Verified charge status",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewayCharge"
                },
                "examples": {
                  "default": {
                    "summary": "Successful response envelope",
                    "value": {
                      "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                      "merchant_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                      "amount": "5000",
                      "currency": "XAF",
                      "channel": "mobile_money",
                      "status": "pending",
                      "created_at": "2026-05-02T10:15:30Z",
                      "success": true,
                      "data": {
                        "id": "obj_01HZX9TRJ4M7YQK6P3W2VBDN5K",
                        "object": "resource",
                        "created_at": "2026-05-02T10:15:30Z"
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      }
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Verify charge with provider.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/gateway/charges/{chargeId}/verify\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/gateway/charges/{chargeId}/verify',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/gateway/charges/{chargeId}/verify\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/gateway/charges/{chargeId}/verify',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/gateway/charges/{chargeId}/cancel": {
      "post": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "Cancel pending charge",
        "operationId": "gatewayCancelCharge",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "chargeId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Charge cancelled",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewayCharge"
                },
                "examples": {
                  "default": {
                    "summary": "Successful response envelope",
                    "value": {
                      "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                      "merchant_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                      "amount": "5000",
                      "currency": "XAF",
                      "channel": "mobile_money",
                      "status": "pending",
                      "created_at": "2026-05-02T10:15:30Z",
                      "success": true,
                      "data": {
                        "id": "obj_01HZX9TRJ4M7YQK6P3W2VBDN5K",
                        "object": "resource",
                        "created_at": "2026-05-02T10:15:30Z"
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      }
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Cancel pending charge.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/gateway/charges/{chargeId}/cancel\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/gateway/charges/{chargeId}/cancel',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/gateway/charges/{chargeId}/cancel\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/gateway/charges/{chargeId}/cancel',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/gateway/fee-estimate": {
      "get": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "Estimate transaction fees",
        "operationId": "gatewayFeeEstimate",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "amount",
            "in": "query",
            "required": true,
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "channel",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "mobile_money",
                "card",
                "bank_transfer",
                "apple_pay",
                "google_pay",
                "ussd",
                "account_funding",
                "paypal"
              ]
            }
          },
          {
            "name": "currency",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "XAF"
            }
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Fee estimate",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/StandardResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/GatewayFeeEstimate"
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Successful response envelope",
                    "value": {
                      "data": {
                        "amount": "5000",
                        "currency": "XAF",
                        "channel": "channel_value",
                        "fee_amount": "200",
                        "net_amount": "4800",
                        "id": "obj_01HZX9TRJ4M7YQK6P3W2VBDN5K",
                        "object": "resource",
                        "created_at": "2026-05-02T10:15:30Z"
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Estimate transaction fees.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/gateway/fee-estimate\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/gateway/fee-estimate',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/gateway/fee-estimate\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/gateway/fee-estimate',\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/gateway/refunds": {
      "post": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "Create refund",
        "operationId": "gatewayCreateRefund",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "MerchantSecretKey": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/XFapiInteractionId"
          },
          {
            "$ref": "#/components/parameters/XFapiCustomerIpAddress"
          },
          {
            "$ref": "#/components/parameters/XFapiAuthDate"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "charge_id"
                ],
                "properties": {
                  "charge_id": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "amount": {
                    "type": "string",
                    "pattern": "^[0-9]{1,15}$",
                    "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits)."
                  },
                  "reason": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Refund created",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/StandardResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/GatewayRefund"
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Successful response envelope",
                    "value": {
                      "data": {
                        "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                        "charge_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                        "amount": "5000",
                        "currency": "XAF",
                        "status": "pending",
                        "object": "resource",
                        "created_at": "2026-05-02T10:15:30Z"
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Create refund.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/gateway/refunds\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/gateway/refunds',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/gateway/refunds\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/gateway/refunds',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      },
      "get": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "List refunds",
        "operationId": "gatewayListRefunds",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "sort_by",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "created_at"
            },
            "description": "Sort field"
          },
          {
            "name": "sort_order",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "asc",
                "desc"
              ],
              "default": "desc"
            },
            "description": "Sort direction"
          },
          {
            "$ref": "#/components/parameters/PageParam"
          },
          {
            "$ref": "#/components/parameters/LimitParam"
          },
          {
            "$ref": "#/components/parameters/CursorParam"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Refunds list",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/GatewayRefund"
                          }
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Cursor-paginated list",
                    "value": {
                      "data": [
                        {
                          "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "charge_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "amount": "5000",
                          "currency": "XAF",
                          "status": "pending",
                          "object": "resource",
                          "created_at": "2026-05-02T10:15:30Z"
                        },
                        {
                          "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "charge_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "amount": "5000",
                          "currency": "XAF",
                          "status": "pending",
                          "object": "resource",
                          "created_at": "2026-05-02T10:15:31Z"
                        }
                      ],
                      "pagination": {
                        "page": 1,
                        "limit": 20,
                        "total": 150,
                        "has_next": true,
                        "has_more": true,
                        "next_cursor": "cursor_01HZX9TRJ4M7YQK6P3W2VBDN5M",
                        "prev_cursor": null,
                        "total_count": 247
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "List refunds.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/gateway/refunds\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/gateway/refunds',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/gateway/refunds\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/gateway/refunds',\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/gateway/refunds/{refundId}": {
      "get": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "Get refund",
        "operationId": "gatewayGetRefund",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "refundId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Refund details",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/StandardResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/GatewayRefund"
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Successful response envelope",
                    "value": {
                      "data": {
                        "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                        "charge_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                        "amount": "5000",
                        "currency": "XAF",
                        "status": "pending",
                        "object": "resource",
                        "created_at": "2026-05-02T10:15:30Z"
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Get refund.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/gateway/refunds/{refundId}\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/gateway/refunds/{refundId}',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/gateway/refunds/{refundId}\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/gateway/refunds/{refundId}',\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/gateway/payouts": {
      "post": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "Create payout",
        "operationId": "gatewayCreatePayout",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "MerchantSecretKey": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/XFapiInteractionId"
          },
          {
            "$ref": "#/components/parameters/XFapiCustomerIpAddress"
          },
          {
            "$ref": "#/components/parameters/XFapiAuthDate"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "merchant_id",
                  "amount",
                  "channel"
                ],
                "properties": {
                  "merchant_id": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "amount": {
                    "type": "string",
                    "pattern": "^[0-9]{1,15}$",
                    "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits). Must be consistent with the currency field."
                  },
                  "currency": {
                    "type": "string",
                    "enum": [
                      "XAF",
                      "XOF",
                      "USD",
                      "EUR",
                      "GBP",
                      "CNY",
                      "NGN",
                      "GHS",
                      "KES",
                      "ZAR"
                    ],
                    "default": "XAF",
                    "description": "ISO 4217 currency code. Default is XAF (Central African CFA Franc)."
                  },
                  "channel": {
                    "type": "string",
                    "enum": [
                      "mobile_money",
                      "bank_transfer"
                    ]
                  },
                  "beneficiary_phone": {
                    "type": "string"
                  },
                  "beneficiary_name": {
                    "type": "string"
                  },
                  "beneficiary_account": {
                    "type": "string"
                  },
                  "beneficiary_bank": {
                    "type": "string"
                  },
                  "narration": {
                    "type": "string"
                  },
                  "tx_ref": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Payout created",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/StandardResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/GatewayPayout"
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Successful response envelope",
                    "value": {
                      "data": {
                        "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                        "merchant_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                        "amount": "10000",
                        "currency": "XAF",
                        "channel": "mobile_money",
                        "status": "pending",
                        "created_at": "2026-05-02T10:15:30Z",
                        "object": "resource"
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Create payout.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/gateway/payouts\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/gateway/payouts',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/gateway/payouts\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/gateway/payouts',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      },
      "get": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "List payouts",
        "operationId": "gatewayListPayouts",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "merchant_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sort_by",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "created_at"
            },
            "description": "Sort field"
          },
          {
            "name": "sort_order",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "asc",
                "desc"
              ],
              "default": "desc"
            },
            "description": "Sort direction"
          },
          {
            "$ref": "#/components/parameters/PageParam"
          },
          {
            "$ref": "#/components/parameters/LimitParam"
          },
          {
            "$ref": "#/components/parameters/CursorParam"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Payouts list",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/GatewayPayout"
                          }
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Cursor-paginated list",
                    "value": {
                      "data": [
                        {
                          "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "merchant_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "amount": "10000",
                          "currency": "XAF",
                          "channel": "mobile_money",
                          "status": "pending",
                          "created_at": "2026-05-02T10:15:30Z",
                          "object": "resource"
                        },
                        {
                          "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "merchant_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "amount": "10000",
                          "currency": "XAF",
                          "channel": "mobile_money",
                          "status": "pending",
                          "created_at": "2026-05-02T10:15:31Z",
                          "object": "resource"
                        }
                      ],
                      "pagination": {
                        "page": 1,
                        "limit": 20,
                        "total": 150,
                        "has_next": true,
                        "has_more": true,
                        "next_cursor": "cursor_01HZX9TRJ4M7YQK6P3W2VBDN5M",
                        "prev_cursor": null,
                        "total_count": 247
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "List payouts.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/gateway/payouts\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/gateway/payouts',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/gateway/payouts\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/gateway/payouts',\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/gateway/payouts/{payoutId}": {
      "get": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "Get payout",
        "operationId": "gatewayGetPayout",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "payoutId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Payout details",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/StandardResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/GatewayPayout"
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Successful response envelope",
                    "value": {
                      "data": {
                        "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                        "merchant_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                        "amount": "10000",
                        "currency": "XAF",
                        "channel": "mobile_money",
                        "status": "pending",
                        "created_at": "2026-05-02T10:15:30Z",
                        "object": "resource"
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Get payout.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/gateway/payouts/{payoutId}\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/gateway/payouts/{payoutId}',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/gateway/payouts/{payoutId}\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/gateway/payouts/{payoutId}',\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/gateway/payout-batches": {
      "post": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "Create payout batch",
        "operationId": "gatewayCreatePayoutBatch",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "merchant_id",
                  "currency",
                  "items"
                ],
                "properties": {
                  "merchant_id": {
                    "type": "string"
                  },
                  "currency": {
                    "type": "string",
                    "enum": [
                      "XAF",
                      "XOF",
                      "USD",
                      "EUR",
                      "GBP",
                      "CNY",
                      "NGN",
                      "GHS",
                      "KES",
                      "ZAR"
                    ],
                    "default": "XAF",
                    "description": "ISO 4217 currency code. Default is XAF (Central African CFA Franc)."
                  },
                  "items": {
                    "type": "array",
                    "items": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Batch created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "status": {
                      "type": "string",
                      "example": "pending"
                    },
                    "items_count": {
                      "type": "integer"
                    },
                    "total_amount": {
                      "type": "string",
                      "pattern": "^[0-9]{1,15}$",
                      "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits). Must be consistent with the currency field."
                    },
                    "currency": {
                      "type": "string",
                      "enum": [
                        "XAF",
                        "XOF",
                        "USD",
                        "EUR",
                        "GBP",
                        "CNY",
                        "NGN",
                        "GHS",
                        "KES",
                        "ZAR"
                      ],
                      "default": "XAF",
                      "description": "ISO 4217 currency code. Default is XAF (Central African CFA Franc)."
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Create payout batch.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/gateway/payout-batches\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/gateway/payout-batches',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/gateway/payout-batches\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/gateway/payout-batches',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/gateway/payout-batches/{batchId}": {
      "get": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "Get payout batch",
        "operationId": "gatewayGetPayoutBatch",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "batchId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Batch details",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string"
                    },
                    "total_amount": {
                      "type": "string",
                      "pattern": "^[0-9]{1,15}$",
                      "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits)."
                    },
                    "items_count": {
                      "type": "integer"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Get payout batch.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/gateway/payout-batches/{batchId}\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/gateway/payout-batches/{batchId}',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/gateway/payout-batches/{batchId}\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/gateway/payout-batches/{batchId}',\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/gateway/payouts/paypal": {
      "post": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "Create PayPal payout",
        "description": "Send money to a PayPal recipient via EMAIL, PHONE, or PAYPAL_ID. Currency must be PayPal-supported (USD, EUR, GBP).",
        "operationId": "gatewayCreatePayPalPayout",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "merchant_id",
                  "amount",
                  "currency",
                  "recipient_type",
                  "receiver",
                  "tx_ref"
                ],
                "properties": {
                  "merchant_id": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "amount": {
                    "type": "string",
                    "example": "5000",
                    "pattern": "^[0-9]{1,15}$",
                    "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits). Must be consistent with the currency field."
                  },
                  "currency": {
                    "type": "string",
                    "example": "USD",
                    "description": "ISO 4217 currency code. Default is XAF (Central African CFA Franc).",
                    "enum": [
                      "XAF",
                      "XOF",
                      "USD",
                      "EUR",
                      "GBP",
                      "CNY",
                      "NGN",
                      "GHS",
                      "KES",
                      "ZAR"
                    ],
                    "default": "XAF"
                  },
                  "recipient_type": {
                    "type": "string",
                    "enum": [
                      "EMAIL",
                      "PHONE",
                      "PAYPAL_ID"
                    ]
                  },
                  "receiver": {
                    "type": "string",
                    "example": "recipient@example.com"
                  },
                  "note": {
                    "type": "string"
                  },
                  "tx_ref": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "PayPal payout created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewayPayout"
                },
                "examples": {
                  "default": {
                    "summary": "Successful response envelope",
                    "value": {
                      "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                      "merchant_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                      "amount": "10000",
                      "currency": "XAF",
                      "channel": "mobile_money",
                      "status": "pending",
                      "created_at": "2026-05-02T10:15:30Z",
                      "success": true,
                      "data": {
                        "id": "obj_01HZX9TRJ4M7YQK6P3W2VBDN5K",
                        "object": "resource",
                        "created_at": "2026-05-02T10:15:30Z"
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      }
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/gateway/payouts/paypal\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/gateway/payouts/paypal',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/gateway/payouts/paypal\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/gateway/payouts/paypal',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/gateway/withdraw-to-paypal": {
      "post": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "Withdraw to PayPal",
        "description": "Withdraw KOB account balance to a PayPal email. Account is debited immediately with automatic reversal on failure.",
        "operationId": "gatewayWithdrawToPayPal",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "amount",
                  "account_id",
                  "paypal_email"
                ],
                "properties": {
                  "amount": {
                    "type": "string",
                    "example": "10000",
                    "pattern": "^[0-9]{1,15}$",
                    "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits). Must be consistent with the currency field."
                  },
                  "account_id": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "paypal_email": {
                    "type": "string",
                    "format": "email"
                  },
                  "currency": {
                    "type": "string",
                    "default": "USD",
                    "enum": [
                      "XAF",
                      "XOF",
                      "USD",
                      "EUR",
                      "GBP",
                      "CNY",
                      "NGN",
                      "GHS",
                      "KES",
                      "ZAR"
                    ],
                    "description": "ISO 4217 currency code. Default is XAF (Central African CFA Franc)."
                  },
                  "narration": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Withdrawal initiated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "amount": {
                      "type": "string",
                      "pattern": "^[0-9]{1,15}$",
                      "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits). Must be consistent with the currency field."
                    },
                    "fee_amount": {
                      "type": "number",
                      "deprecated": true,
                      "x-successor": "fee_amount_money",
                      "x-sunset": "5.0.0",
                      "description": "Deprecated: floating-point monetary value (IEEE-754 binary64 cannot represent decimal minor units exactly). Use `fee_amount_money` instead. Removal is scheduled for v5.0.0."
                    },
                    "total_debited": {
                      "type": "number",
                      "deprecated": true,
                      "x-successor": "total_debited_money",
                      "x-sunset": "5.0.0",
                      "description": "Deprecated: floating-point monetary value (IEEE-754 binary64 cannot represent decimal minor units exactly). Use `total_debited_money` instead. Removal is scheduled for v5.0.0."
                    },
                    "currency": {
                      "type": "string",
                      "enum": [
                        "XAF",
                        "XOF",
                        "USD",
                        "EUR",
                        "GBP",
                        "CNY",
                        "NGN",
                        "GHS",
                        "KES",
                        "ZAR"
                      ],
                      "default": "XAF",
                      "description": "ISO 4217 currency code. Default is XAF (Central African CFA Franc)."
                    },
                    "status": {
                      "type": "string"
                    },
                    "paypal_email": {
                      "type": "string"
                    },
                    "batch_id": {
                      "type": "string"
                    },
                    "tx_ref": {
                      "type": "string"
                    },
                    "fee_amount_money": {
                      "$ref": "#/components/schemas/Money",
                      "description": "Canonical string-encoded successor to `fee_amount`. Amount and ISO 4217 currency travel together (ISO 20022 ActiveCurrencyAndAmount). Prefer this field: it is exact for zero-decimal currencies (XAF, XOF) and immune to IEEE-754 drift.",
                      "x-added-in": "4.54.0"
                    },
                    "total_debited_money": {
                      "$ref": "#/components/schemas/Money",
                      "description": "Canonical string-encoded successor to `total_debited`. Amount and ISO 4217 currency travel together (ISO 20022 ActiveCurrencyAndAmount). Prefer this field: it is exact for zero-decimal currencies (XAF, XOF) and immune to IEEE-754 drift.",
                      "x-added-in": "4.54.0"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/gateway/withdraw-to-paypal\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/gateway/withdraw-to-paypal',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/gateway/withdraw-to-paypal\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/gateway/withdraw-to-paypal',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/gateway/disputes": {
      "get": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "List disputes",
        "operationId": "gatewayListDisputes",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 25,
              "maximum": 100
            },
            "description": "Items per page"
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 0
            },
            "description": "Items to skip"
          },
          {
            "name": "sort_by",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "created_at"
            },
            "description": "Sort field"
          },
          {
            "name": "sort_order",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "asc",
                "desc"
              ],
              "default": "desc"
            },
            "description": "Sort direction"
          },
          {
            "$ref": "#/components/parameters/StartingAfter"
          },
          {
            "$ref": "#/components/parameters/EndingBefore"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Disputes list",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/GatewayDispute"
                          }
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Cursor-paginated list",
                    "value": {
                      "data": [
                        {
                          "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "charge_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "amount": "5000",
                          "currency": "XAF",
                          "status": "open",
                          "object": "resource",
                          "created_at": "2026-05-02T10:15:30Z"
                        },
                        {
                          "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "charge_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "amount": "5000",
                          "currency": "XAF",
                          "status": "open",
                          "object": "resource",
                          "created_at": "2026-05-02T10:15:31Z"
                        }
                      ],
                      "pagination": {
                        "page": 1,
                        "limit": 20,
                        "total": 150,
                        "has_next": true,
                        "has_more": true,
                        "next_cursor": "cursor_01HZX9TRJ4M7YQK6P3W2VBDN5M",
                        "prev_cursor": null,
                        "total_count": 247
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "List disputes.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/gateway/disputes\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/gateway/disputes',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/gateway/disputes\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/gateway/disputes',\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/gateway/disputes/{disputeId}": {
      "get": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "Get dispute",
        "operationId": "gatewayGetDispute",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "disputeId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Dispute details",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/StandardResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/GatewayDispute"
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Successful response envelope",
                    "value": {
                      "data": {
                        "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                        "charge_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                        "amount": "5000",
                        "currency": "XAF",
                        "status": "open",
                        "object": "resource",
                        "created_at": "2026-05-02T10:15:30Z"
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Get dispute.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/gateway/disputes/{disputeId}\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/gateway/disputes/{disputeId}',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/gateway/disputes/{disputeId}\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/gateway/disputes/{disputeId}',\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/gateway/disputes/{disputeId}/evidence": {
      "post": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "Submit dispute evidence",
        "operationId": "gatewaySubmitDisputeEvidence",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "disputeId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "evidence_text"
                ],
                "properties": {
                  "evidence_text": {
                    "type": "string"
                  },
                  "evidence_type": {
                    "type": "string"
                  },
                  "file_url": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Evidence submitted",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Submit dispute evidence.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/gateway/disputes/{disputeId}/evidence\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/gateway/disputes/{disputeId}/evidence',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/gateway/disputes/{disputeId}/evidence\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/gateway/disputes/{disputeId}/evidence',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/gateway/settlements": {
      "get": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "List settlements",
        "operationId": "gatewayListSettlements",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "merchant_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 25,
              "maximum": 100
            },
            "description": "Items per page"
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 0
            },
            "description": "Items to skip"
          },
          {
            "name": "sort_by",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "created_at"
            },
            "description": "Sort field"
          },
          {
            "name": "sort_order",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "asc",
                "desc"
              ],
              "default": "desc"
            },
            "description": "Sort direction"
          },
          {
            "$ref": "#/components/parameters/StartingAfter"
          },
          {
            "$ref": "#/components/parameters/EndingBefore"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Settlements list",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/GatewaySettlement"
                          }
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Cursor-paginated list",
                    "value": {
                      "data": [
                        {
                          "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "merchant_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "amount": "450000",
                          "currency": "XAF",
                          "status": "pending",
                          "object": "resource",
                          "created_at": "2026-05-02T10:15:30Z"
                        },
                        {
                          "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "merchant_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "amount": "450000",
                          "currency": "XAF",
                          "status": "pending",
                          "object": "resource",
                          "created_at": "2026-05-02T10:15:31Z"
                        }
                      ],
                      "pagination": {
                        "page": 1,
                        "limit": 20,
                        "total": 150,
                        "has_next": true,
                        "has_more": true,
                        "next_cursor": "cursor_01HZX9TRJ4M7YQK6P3W2VBDN5M",
                        "prev_cursor": null,
                        "total_count": 247
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "List settlements.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/gateway/settlements\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/gateway/settlements',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/gateway/settlements\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/gateway/settlements',\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/gateway/settlements/{settlementId}": {
      "get": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "Get settlement",
        "operationId": "gatewayGetSettlement",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "settlementId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Settlement details",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/StandardResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/GatewaySettlement"
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Successful response envelope",
                    "value": {
                      "data": {
                        "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                        "merchant_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                        "amount": "450000",
                        "currency": "XAF",
                        "status": "pending",
                        "object": "resource",
                        "created_at": "2026-05-02T10:15:30Z"
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Get settlement.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/gateway/settlements/{settlementId}\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/gateway/settlements/{settlementId}',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/gateway/settlements/{settlementId}\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/gateway/settlements/{settlementId}',\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/gateway/beneficiaries": {
      "post": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "Create beneficiary",
        "operationId": "gatewayCreateBeneficiary",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "merchant_id",
                  "name",
                  "channel"
                ],
                "properties": {
                  "merchant_id": {
                    "type": "string"
                  },
                  "name": {
                    "type": "string"
                  },
                  "channel": {
                    "type": "string"
                  },
                  "phone": {
                    "type": "string"
                  },
                  "bank_account": {
                    "type": "string"
                  },
                  "bank_code": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Beneficiary created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewayBeneficiary"
                },
                "examples": {
                  "default": {
                    "summary": "Successful response envelope",
                    "value": {
                      "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                      "merchant_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                      "name": "name_value",
                      "channel": "mobile_money",
                      "success": true,
                      "data": {
                        "id": "obj_01HZX9TRJ4M7YQK6P3W2VBDN5K",
                        "object": "resource",
                        "created_at": "2026-05-02T10:15:30Z"
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      }
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Create beneficiary.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/gateway/beneficiaries\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/gateway/beneficiaries',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/gateway/beneficiaries\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/gateway/beneficiaries',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      },
      "get": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "List beneficiaries",
        "operationId": "gatewayListBeneficiaries",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "merchant_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 25,
              "maximum": 100,
              "minimum": 1
            },
            "description": "Items per page"
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 0
            },
            "description": "Items to skip"
          },
          {
            "name": "sort_by",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "created_at"
            },
            "description": "Sort field"
          },
          {
            "name": "sort_order",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "asc",
                "desc"
              ],
              "default": "desc"
            },
            "description": "Sort direction"
          },
          {
            "$ref": "#/components/parameters/StartingAfter"
          },
          {
            "$ref": "#/components/parameters/EndingBefore"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          },
          {
            "$ref": "#/components/parameters/CursorParam"
          }
        ],
        "responses": {
          "200": {
            "description": "Beneficiaries list",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/GatewayBeneficiary"
                          }
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Cursor-paginated list",
                    "value": {
                      "data": [
                        {
                          "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "merchant_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "name": "name_value",
                          "channel": "mobile_money",
                          "object": "resource",
                          "created_at": "2026-05-02T10:15:30Z"
                        },
                        {
                          "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "merchant_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "name": "name_value",
                          "channel": "mobile_money",
                          "object": "resource",
                          "created_at": "2026-05-02T10:15:31Z"
                        }
                      ],
                      "pagination": {
                        "page": 1,
                        "limit": 20,
                        "total": 150,
                        "has_next": true,
                        "has_more": true,
                        "next_cursor": "cursor_01HZX9TRJ4M7YQK6P3W2VBDN5M",
                        "prev_cursor": null,
                        "total_count": 247
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              },
              "X-Pagination-Mode": {
                "description": "Pagination mode used for this response (always `cursor` for d.2A operations).",
                "schema": {
                  "type": "string",
                  "enum": [
                    "cursor"
                  ]
                }
              },
              "X-Pagination-Has-More": {
                "description": "Boolean flag (`true`/`false`) indicating whether more pages are available.",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true",
                    "false"
                  ]
                }
              },
              "X-Pagination-Next-Cursor": {
                "description": "Opaque continuation cursor. Omitted when has_more is false.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Pagination-Limit": {
                "description": "Effective per-page limit used for this response.",
                "schema": {
                  "type": "integer",
                  "minimum": 1,
                  "maximum": 100
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "List beneficiaries.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/gateway/beneficiaries\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/gateway/beneficiaries',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/gateway/beneficiaries\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/gateway/beneficiaries',\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/gateway/beneficiaries/{beneficiaryId}": {
      "delete": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "Delete beneficiary",
        "operationId": "gatewayDeleteBeneficiary",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "beneficiaryId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "204": {
            "description": "Beneficiary deleted",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            },
            "content": {
              "application/json": {
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Delete beneficiary.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X DELETE \"https://api.kangopenbanking.com/v1/gateway/beneficiaries/{beneficiaryId}\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'DELETE',\n  path: '/v1/gateway/beneficiaries/{beneficiaryId}',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"DELETE\",\n    path=\"/v1/gateway/beneficiaries/{beneficiaryId}\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'DELETE',\n    'path'   => '/v1/gateway/beneficiaries/{beneficiaryId}',\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/gateway/reports/transactions": {
      "get": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "Transaction report",
        "operationId": "gatewayReportTransactions",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "merchant_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "from",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "to",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "format",
            "in": "query",
            "description": "Response format. Defaults to JSON. Use \"csv\" for spreadsheet export.",
            "schema": {
              "type": "string",
              "enum": [
                "json",
                "csv"
              ],
              "default": "json"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 1000,
              "default": 100
            }
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          },
          {
            "$ref": "#/components/parameters/StartingAfter"
          },
          {
            "$ref": "#/components/parameters/EndingBefore"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Transaction report with summary",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/GatewayCharge"
                          }
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Cursor-paginated list",
                    "value": {
                      "data": [
                        {
                          "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "merchant_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "amount": "5000",
                          "currency": "XAF",
                          "channel": "mobile_money",
                          "status": "pending",
                          "created_at": "2026-05-02T10:15:30Z",
                          "object": "resource"
                        },
                        {
                          "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "merchant_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "amount": "5000",
                          "currency": "XAF",
                          "channel": "mobile_money",
                          "status": "pending",
                          "created_at": "2026-05-02T10:15:31Z",
                          "object": "resource"
                        }
                      ],
                      "pagination": {
                        "page": 1,
                        "limit": 20,
                        "total": 150,
                        "has_next": true,
                        "has_more": true,
                        "next_cursor": "cursor_01HZX9TRJ4M7YQK6P3W2VBDN5M",
                        "prev_cursor": null,
                        "total_count": 247
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              },
              "text/csv": {
                "schema": {
                  "type": "string",
                  "format": "binary",
                  "description": "CSV file (RFC 4180). Headers in first row."
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Transaction report.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/gateway/reports/transactions\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/gateway/reports/transactions',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/gateway/reports/transactions\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/gateway/reports/transactions',\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/gateway/reports/settlements": {
      "get": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "Settlement report",
        "operationId": "gatewayReportSettlements",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "merchant_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "from",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "to",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "format",
            "in": "query",
            "description": "Response format. Defaults to JSON. Use \"csv\" for spreadsheet export.",
            "schema": {
              "type": "string",
              "enum": [
                "json",
                "csv"
              ],
              "default": "json"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 1000,
              "default": 100
            }
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          },
          {
            "$ref": "#/components/parameters/StartingAfter"
          },
          {
            "$ref": "#/components/parameters/EndingBefore"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Settlement report with summary",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/GatewaySettlement"
                          }
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Cursor-paginated list",
                    "value": {
                      "data": [
                        {
                          "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "merchant_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "amount": "450000",
                          "currency": "XAF",
                          "status": "pending",
                          "object": "resource",
                          "created_at": "2026-05-02T10:15:30Z"
                        },
                        {
                          "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "merchant_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "amount": "450000",
                          "currency": "XAF",
                          "status": "pending",
                          "object": "resource",
                          "created_at": "2026-05-02T10:15:31Z"
                        }
                      ],
                      "pagination": {
                        "page": 1,
                        "limit": 20,
                        "total": 150,
                        "has_next": true,
                        "has_more": true,
                        "next_cursor": "cursor_01HZX9TRJ4M7YQK6P3W2VBDN5M",
                        "prev_cursor": null,
                        "total_count": 247
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              },
              "text/csv": {
                "schema": {
                  "type": "string",
                  "format": "binary",
                  "description": "CSV file (RFC 4180). Headers in first row."
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Settlement report.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/gateway/reports/settlements\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/gateway/reports/settlements',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/gateway/reports/settlements\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/gateway/reports/settlements',\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/gateway/export/transactions": {
      "get": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "Export transactions as CSV",
        "operationId": "gatewayExportTransactions",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "merchant_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "from",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "to",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "format",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "csv"
            }
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          },
          {
            "$ref": "#/components/parameters/LimitParam"
          },
          {
            "$ref": "#/components/parameters/CursorParam"
          }
        ],
        "responses": {
          "200": {
            "description": "CSV file download",
            "content": {
              "text/csv": {
                "schema": {
                  "type": "string"
                }
              },
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "download_url": {
                      "type": "string",
                      "format": "uri"
                    },
                    "expires_at": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "row_count": {
                      "type": "integer"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/PaginatedList"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Export transactions as CSV.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/gateway/export/transactions\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/gateway/export/transactions',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/gateway/export/transactions\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/gateway/export/transactions',\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/gateway/charges/preauth": {
      "post": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "Create preauthorized charge",
        "description": "Hold funds on a card without immediately capturing. Uses Stripe PaymentIntent with capture_method=manual.",
        "operationId": "gatewayPreauthCharge",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "merchant_id",
                  "amount",
                  "tx_ref"
                ],
                "properties": {
                  "merchant_id": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "amount": {
                    "type": "string",
                    "example": "50000",
                    "pattern": "^[0-9]{1,15}$",
                    "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits). Must be consistent with the currency field."
                  },
                  "currency": {
                    "type": "string",
                    "default": "USD",
                    "enum": [
                      "XAF",
                      "XOF",
                      "USD",
                      "EUR",
                      "GBP",
                      "CNY",
                      "NGN",
                      "GHS",
                      "KES",
                      "ZAR"
                    ],
                    "description": "ISO 4217 currency code. Default is XAF (Central African CFA Franc)."
                  },
                  "customer_email": {
                    "type": "string"
                  },
                  "customer_name": {
                    "type": "string"
                  },
                  "tx_ref": {
                    "type": "string"
                  },
                  "metadata": {
                    "type": "object"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Preauthorized charge created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewayCharge"
                },
                "examples": {
                  "default": {
                    "summary": "Successful response envelope",
                    "value": {
                      "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                      "merchant_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                      "amount": "5000",
                      "currency": "XAF",
                      "channel": "mobile_money",
                      "status": "pending",
                      "created_at": "2026-05-02T10:15:30Z",
                      "success": true,
                      "data": {
                        "id": "obj_01HZX9TRJ4M7YQK6P3W2VBDN5K",
                        "object": "resource",
                        "created_at": "2026-05-02T10:15:30Z"
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      }
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/gateway/charges/preauth\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/gateway/charges/preauth',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/gateway/charges/preauth\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/gateway/charges/preauth',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/gateway/charges/{chargeId}/capture": {
      "post": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "Capture authorized charge",
        "description": "Capture authorized charge.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "operationId": "gatewayCaptureCharge",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "chargeId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "amount": {
                    "type": "string",
                    "description": "Partial capture amount. Omit for full capture. Represented as a string integer in the currency's minor unit (XAF has no subunits).",
                    "pattern": "^[0-9]{1,15}$"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Charge captured",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string"
                    },
                    "captured_amount": {
                      "type": "number",
                      "deprecated": true,
                      "x-successor": "captured_amount_money",
                      "x-sunset": "5.0.0",
                      "description": "Deprecated: floating-point monetary value (IEEE-754 binary64 cannot represent decimal minor units exactly). Use `captured_amount_money` instead. Removal is scheduled for v5.0.0."
                    },
                    "captured_amount_money": {
                      "$ref": "#/components/schemas/Money",
                      "description": "Canonical string-encoded successor to `captured_amount`. Amount and ISO 4217 currency travel together (ISO 20022 ActiveCurrencyAndAmount). Prefer this field: it is exact for zero-decimal currencies (XAF, XOF) and immune to IEEE-754 drift.",
                      "x-added-in": "4.54.0"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/gateway/charges/{chargeId}/capture\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/gateway/charges/{chargeId}/capture',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/gateway/charges/{chargeId}/capture\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/gateway/charges/{chargeId}/capture',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/gateway/charges/{chargeId}/void": {
      "post": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "Void authorized charge",
        "description": "Void authorized charge.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "operationId": "gatewayVoidCharge",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "chargeId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "charge_id"
                ],
                "properties": {
                  "charge_id": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Charge voided",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string",
                      "example": "voided"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/gateway/charges/{chargeId}/void\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/gateway/charges/{chargeId}/void',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/gateway/charges/{chargeId}/void\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/gateway/charges/{chargeId}/void',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/gateway/charges/validate": {
      "post": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "Validate charge with OTP",
        "description": "Submit an OTP to complete a pending mobile money or card charge that requires validation.",
        "operationId": "gatewayValidateCharge",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "charge_id",
                  "otp"
                ],
                "properties": {
                  "charge_id": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "otp": {
                    "type": "string",
                    "example": "123456"
                  },
                  "flw_ref": {
                    "type": "string",
                    "description": "Flutterwave reference (optional, auto-resolved from charge)"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Charge validation result",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "successful",
                        "failed"
                      ]
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/gateway/charges/validate\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/gateway/charges/validate',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/gateway/charges/validate\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/gateway/charges/validate',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/gateway/virtual-accounts": {
      "post": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "Create virtual account (Nium)",
        "description": "Provision a dedicated Nium virtual receiving account. Supports 17 source currencies (USD, EUR, GBP, AUD, CAD, SGD, AED, JPY, INR, ZAR, HKD, CHF, NZD, SEK, NOK, DKK, CNY) with XAF as the locked destination currency. `account_kind=\"global\"` returns IBAN/SWIFT details for cross-border collections.\n\n**Migration:** Replace with `createGlobalAccount`. Create a Nium global account for new integrations. Existing virtual accounts continue to receive funds until the sunset date.",
        "operationId": "gatewayCreateVirtualAccount",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "merchant_id",
                  "email"
                ],
                "properties": {
                  "merchant_id": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "email": {
                    "type": "string"
                  },
                  "beneficiary_name": {
                    "type": "string",
                    "description": "Must match the KYC-verified legal name on file."
                  },
                  "account_kind": {
                    "type": "string",
                    "enum": [
                      "virtual",
                      "global"
                    ],
                    "default": "virtual"
                  },
                  "currency": {
                    "type": "string",
                    "enum": [
                      "USD",
                      "EUR",
                      "GBP",
                      "AUD",
                      "CAD",
                      "SGD",
                      "AED",
                      "JPY",
                      "INR",
                      "ZAR",
                      "HKD",
                      "CHF",
                      "NZD",
                      "SEK",
                      "NOK",
                      "DKK",
                      "CNY"
                    ],
                    "default": "USD",
                    "description": "Receiving currency for the Nium-issued account."
                  },
                  "pop_code": {
                    "type": "string",
                    "description": "BEAC Purpose-of-Payment code (whitelist enforced)."
                  },
                  "bvn": {
                    "type": "string",
                    "deprecated": true,
                    "description": "DEPRECATED. Legacy NGN-rail Bank Verification Number. Ignored on Nium provisioning; accepted only for backward compatibility. Requests including `bvn` will succeed but the field is stripped server-side and returned as a warning in `meta.warnings[]`."
                  },
                  "is_permanent": {
                    "type": "boolean",
                    "default": true,
                    "description": "Nium accounts are permanent by default."
                  },
                  "narration": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Virtual account created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewayVirtualAccount"
                },
                "examples": {
                  "default": {
                    "summary": "Successful response envelope",
                    "value": {
                      "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                      "merchant_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                      "account_number": "GB29NWBK60161331926819",
                      "bank_name": "Citibank N.A. (via Nium)",
                      "currency": "USD",
                      "success": true,
                      "data": {
                        "id": "obj_01HZX9TRJ4M7YQK6P3W2VBDN5K",
                        "object": "resource",
                        "created_at": "2026-05-02T10:15:30Z"
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      }
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/gateway/virtual-accounts\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/gateway/virtual-accounts',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/gateway/virtual-accounts\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/gateway/virtual-accounts',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ],
        "deprecated": true,
        "x-sunset": "2027-01-01",
        "x-deprecation-notice": "Use /v1/gateway/global-accounts (Nium) for new integrations. This endpoint will be removed on 2027-01-01.",
        "x-replacement-operation-ids": [
          "createGlobalAccount"
        ],
        "x-migration-guide": "Create a Nium global account for new integrations. Existing virtual accounts continue to receive funds until the sunset date."
      },
      "get": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "List virtual accounts",
        "operationId": "gatewayListVirtualAccounts",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "merchant_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Number of items per page. Defaults to 25. Maximum 100.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 25,
              "example": 25
            }
          },
          {
            "$ref": "#/components/parameters/CursorParam"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          },
          {
            "name": "account_kind",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "virtual",
                "global"
              ]
            },
            "description": "Filter by Nium account class."
          }
        ],
        "responses": {
          "200": {
            "description": "Virtual accounts list",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/GatewayVirtualAccount"
                          }
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Cursor-paginated list",
                    "value": {
                      "data": [
                        {
                          "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "merchant_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "account_number": "GB29NWBK60161331926819",
                          "bank_name": "Citibank N.A. (via Nium)",
                          "currency": "USD",
                          "object": "resource",
                          "created_at": "2026-05-02T10:15:30Z"
                        },
                        {
                          "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "merchant_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "account_number": "GB29NWBK60161331926819",
                          "bank_name": "Citibank N.A. (via Nium)",
                          "currency": "USD",
                          "object": "resource",
                          "created_at": "2026-05-02T10:15:31Z"
                        }
                      ],
                      "pagination": {
                        "page": 1,
                        "limit": 20,
                        "total": 150,
                        "has_next": true,
                        "has_more": true,
                        "next_cursor": "cursor_01HZX9TRJ4M7YQK6P3W2VBDN5M",
                        "prev_cursor": null,
                        "total_count": 247
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              },
              "X-Pagination-Mode": {
                "description": "Pagination mode used for this response (always `cursor` for d.2A operations).",
                "schema": {
                  "type": "string",
                  "enum": [
                    "cursor"
                  ]
                }
              },
              "X-Pagination-Has-More": {
                "description": "Boolean flag (`true`/`false`) indicating whether more pages are available.",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true",
                    "false"
                  ]
                }
              },
              "X-Pagination-Next-Cursor": {
                "description": "Opaque continuation cursor. Omitted when has_more is false.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Pagination-Limit": {
                "description": "Effective per-page limit used for this response.",
                "schema": {
                  "type": "integer",
                  "minimum": 1,
                  "maximum": 100
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "List virtual accounts.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.\n\n**Migration:** Replace with `listGlobalAccounts`. List global accounts. Virtual accounts created before migration remain readable here until the sunset date.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/gateway/virtual-accounts\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/gateway/virtual-accounts',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/gateway/virtual-accounts\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/gateway/virtual-accounts',\n]);\n\nprint_r($response->data);"
          }
        ],
        "deprecated": true,
        "x-sunset": "2027-01-01",
        "x-deprecation-notice": "Use /v1/gateway/global-accounts (Nium) for new integrations. This endpoint will be removed on 2027-01-01.",
        "x-replacement-operation-ids": [
          "listGlobalAccounts"
        ],
        "x-migration-guide": "List global accounts. Virtual accounts created before migration remain readable here until the sunset date."
      }
    },
    "/v1/gateway/virtual-accounts/{accountId}": {
      "get": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "Get virtual account",
        "operationId": "gatewayGetVirtualAccount",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "accountId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Virtual account details",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/StandardResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/GatewayVirtualAccount"
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Successful response envelope",
                    "value": {
                      "data": {
                        "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                        "merchant_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                        "account_number": "GB29NWBK60161331926819",
                        "bank_name": "Citibank N.A. (via Nium)",
                        "currency": "USD",
                        "object": "resource",
                        "created_at": "2026-05-02T10:15:30Z"
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Get virtual account.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.\n\n**Migration:** Replace with `listGlobalAccounts`. No single-item global account read exists; filter `listGlobalAccounts` results by account identifier.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/gateway/virtual-accounts/{accountId}\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/gateway/virtual-accounts/{accountId}',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/gateway/virtual-accounts/{accountId}\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/gateway/virtual-accounts/{accountId}',\n]);\n\nprint_r($response->data);"
          }
        ],
        "deprecated": true,
        "x-sunset": "2027-01-01",
        "x-deprecation-notice": "Use /v1/gateway/global-accounts (Nium) for new integrations. This endpoint will be removed on 2027-01-01.",
        "x-replacement-operation-ids": [
          "listGlobalAccounts"
        ],
        "x-migration-guide": "No single-item global account read exists; filter `listGlobalAccounts` results by account identifier."
      }
    },
    "/v1/gateway/balances": {
      "get": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "Get merchant balances",
        "description": "Get merchant balances.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "operationId": "gatewayGetMerchantBalance",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "merchant_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/LimitParam"
          },
          {
            "$ref": "#/components/parameters/CursorParam"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Merchant wallet balances",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/GatewayMerchantWallet"
                          }
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Account balance snapshot",
                    "value": {
                      "data": [
                        {
                          "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "merchant_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "currency": "XAF",
                          "available_balance": "500000"
                        }
                      ],
                      "pagination": {
                        "page": 1,
                        "limit": 20,
                        "total": 150,
                        "has_next": true
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/gateway/balances\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/gateway/balances',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/gateway/balances\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/gateway/balances',\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/gateway/verify-bank-account": {
      "post": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "Verify bank account",
        "description": "Verify bank account.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "operationId": "gatewayVerifyBankAccount",
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "account_number",
                  "account_bank"
                ],
                "properties": {
                  "account_number": {
                    "type": "string",
                    "example": "1234567890"
                  },
                  "account_bank": {
                    "type": "string",
                    "example": "044",
                    "description": "Bank code"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Account verification result",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewayBankVerification"
                },
                "examples": {
                  "default": {
                    "summary": "Successful response envelope",
                    "value": {
                      "account_name": "John Doe",
                      "account_number": "1234567890",
                      "success": true,
                      "data": {
                        "id": "obj_01HZX9TRJ4M7YQK6P3W2VBDN5K",
                        "object": "resource",
                        "created_at": "2026-05-02T10:15:30Z"
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      }
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Recommended for safe retries. UUID v4. When supplied, duplicate requests within 24h replay the original response. See Idempotency guide."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/gateway/verify-bank-account\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/gateway/verify-bank-account',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/gateway/verify-bank-account\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/gateway/verify-bank-account',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/gateway/resolve-bvn": {
      "post": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "Resolve BVN",
        "description": "Resolve BVN.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.\n\n**CEMAC callers:** prefer `/v1/verify/nin` or `/v1/verify/cni`. The BVN endpoint targets the Nigerian Bank Verification Number registry and is retained for NG deployments only. Responses include `Link: <https://api.kangopenbanking.com/v1/verify/nin>; rel=\"successor-version\"` per RFC 8288 to aid client migration.",
        "operationId": "gatewayResolveBvn",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "bvn"
                ],
                "properties": {
                  "bvn": {
                    "type": "string",
                    "example": "12345678901"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "BVN resolution result",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewayBvnResolution"
                },
                "examples": {
                  "default": {
                    "summary": "Successful response envelope",
                    "value": {
                      "bvn": "bvn_value",
                      "first_name": "first_name_value",
                      "last_name": "last_name_value",
                      "success": true,
                      "data": {
                        "id": "obj_01HZX9TRJ4M7YQK6P3W2VBDN5K",
                        "object": "resource",
                        "created_at": "2026-05-02T10:15:30Z"
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      }
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              },
              "Link": {
                "$ref": "#/components/headers/LinkSuccessor"
              },
              "Deprecation": {
                "$ref": "#/components/headers/Deprecation"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "Link": {
                "$ref": "#/components/headers/LinkSuccessor"
              },
              "Deprecation": {
                "$ref": "#/components/headers/Deprecation"
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "Link": {
                "$ref": "#/components/headers/LinkSuccessor"
              },
              "Deprecation": {
                "$ref": "#/components/headers/Deprecation"
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "Link": {
                "$ref": "#/components/headers/LinkSuccessor"
              },
              "Deprecation": {
                "$ref": "#/components/headers/Deprecation"
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "Link": {
                "$ref": "#/components/headers/LinkSuccessor"
              },
              "Deprecation": {
                "$ref": "#/components/headers/Deprecation"
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "Link": {
                "$ref": "#/components/headers/LinkSuccessor"
              },
              "Deprecation": {
                "$ref": "#/components/headers/Deprecation"
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "Link": {
                "$ref": "#/components/headers/LinkSuccessor"
              },
              "Deprecation": {
                "$ref": "#/components/headers/Deprecation"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "Link": {
                "$ref": "#/components/headers/LinkSuccessor"
              },
              "Deprecation": {
                "$ref": "#/components/headers/Deprecation"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Recommended for safe retries. UUID v4. When supplied, duplicate requests within 24h replay the original response. See Idempotency guide."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/gateway/resolve-bvn\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/gateway/resolve-bvn',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/gateway/resolve-bvn\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/gateway/resolve-bvn',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ],
        "deprecated": false,
        "x-deprecated-for-region": [
          "CEMAC"
        ]
      }
    },
    "/v1/gateway/fund-account": {
      "post": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "Fund a KOB account",
        "description": "Add funds to a user's KOB account via Mobile Money, Card, or Bank Transfer. On successful provider charge, the account balance is automatically credited.",
        "operationId": "gatewayFundAccount",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "amount",
                  "channel",
                  "account_id"
                ],
                "properties": {
                  "amount": {
                    "type": "string",
                    "example": "50000",
                    "pattern": "^[0-9]{1,15}$",
                    "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits). Must be consistent with the currency field."
                  },
                  "currency": {
                    "type": "string",
                    "default": "XAF",
                    "enum": [
                      "XAF",
                      "XOF",
                      "USD",
                      "EUR",
                      "GBP",
                      "CNY",
                      "NGN",
                      "GHS",
                      "KES",
                      "ZAR"
                    ],
                    "description": "ISO 4217 currency code. Default is XAF (Central African CFA Franc)."
                  },
                  "channel": {
                    "type": "string",
                    "enum": [
                      "mobile_money",
                      "card",
                      "bank_transfer"
                    ]
                  },
                  "account_id": {
                    "type": "string",
                    "format": "uuid",
                    "description": "Target KOB account to credit"
                  },
                  "source_phone": {
                    "type": "string",
                    "description": "Required for mobile_money"
                  },
                  "source_email": {
                    "type": "string",
                    "description": "Required for card"
                  },
                  "metadata": {
                    "type": "object"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Funding charge initiated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "account_id": {
                      "type": "string"
                    },
                    "amount": {
                      "type": "string",
                      "pattern": "^[0-9]{1,15}$",
                      "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits). Must be consistent with the currency field."
                    },
                    "currency": {
                      "type": "string",
                      "enum": [
                        "XAF",
                        "XOF",
                        "USD",
                        "EUR",
                        "GBP",
                        "CNY",
                        "NGN",
                        "GHS",
                        "KES",
                        "ZAR"
                      ],
                      "default": "XAF",
                      "description": "ISO 4217 currency code. Default is XAF (Central African CFA Franc)."
                    },
                    "channel": {
                      "type": "string"
                    },
                    "provider": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string"
                    },
                    "fee_amount": {
                      "type": "number",
                      "deprecated": true,
                      "x-successor": "fee_amount_money",
                      "x-sunset": "5.0.0",
                      "description": "Deprecated: floating-point monetary value (IEEE-754 binary64 cannot represent decimal minor units exactly). Use `fee_amount_money` instead. Removal is scheduled for v5.0.0."
                    },
                    "net_amount": {
                      "type": "number",
                      "deprecated": true,
                      "x-successor": "net_amount_money",
                      "x-sunset": "5.0.0",
                      "description": "Deprecated: floating-point monetary value (IEEE-754 binary64 cannot represent decimal minor units exactly). Use `net_amount_money` instead. Removal is scheduled for v5.0.0."
                    },
                    "tx_ref": {
                      "type": "string"
                    },
                    "redirect_url": {
                      "type": "string"
                    },
                    "created_at": {
                      "type": "string"
                    },
                    "fee_amount_money": {
                      "$ref": "#/components/schemas/Money",
                      "description": "Canonical string-encoded successor to `fee_amount`. Amount and ISO 4217 currency travel together (ISO 20022 ActiveCurrencyAndAmount). Prefer this field: it is exact for zero-decimal currencies (XAF, XOF) and immune to IEEE-754 drift.",
                      "x-added-in": "4.54.0"
                    },
                    "net_amount_money": {
                      "$ref": "#/components/schemas/Money",
                      "description": "Canonical string-encoded successor to `net_amount`. Amount and ISO 4217 currency travel together (ISO 20022 ActiveCurrencyAndAmount). Prefer this field: it is exact for zero-decimal currencies (XAF, XOF) and immune to IEEE-754 drift.",
                      "x-added-in": "4.54.0"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/gateway/fund-account\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/gateway/fund-account',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/gateway/fund-account\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/gateway/fund-account',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/gateway/withdraw-to-bank": {
      "post": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "Withdraw to external bank",
        "description": "Withdraw funds from a user's KOB account to an external bank account via Flutterwave. Debits the account immediately; reverses if payout fails.",
        "operationId": "gatewayWithdrawToBank",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "amount",
                  "account_id",
                  "account_number",
                  "beneficiary_name"
                ],
                "properties": {
                  "amount": {
                    "type": "string",
                    "example": "25000",
                    "pattern": "^[0-9]{1,15}$",
                    "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits)."
                  },
                  "account_id": {
                    "type": "string",
                    "format": "uuid",
                    "description": "Source KOB account to debit"
                  },
                  "bank_code": {
                    "type": "string",
                    "example": "SGCM"
                  },
                  "account_number": {
                    "type": "string",
                    "example": "1234567890"
                  },
                  "beneficiary_name": {
                    "type": "string",
                    "example": "Jean Dupont"
                  },
                  "narration": {
                    "type": "string"
                  },
                  "channel": {
                    "type": "string",
                    "default": "bank_transfer"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Withdrawal initiated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "account_id": {
                      "type": "string"
                    },
                    "amount": {
                      "type": "string",
                      "pattern": "^[0-9]{1,15}$",
                      "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits). Must be consistent with the currency field."
                    },
                    "fee_amount": {
                      "type": "number",
                      "deprecated": true,
                      "x-successor": "fee_amount_money",
                      "x-sunset": "5.0.0",
                      "description": "Deprecated: floating-point monetary value (IEEE-754 binary64 cannot represent decimal minor units exactly). Use `fee_amount_money` instead. Removal is scheduled for v5.0.0."
                    },
                    "total_debited": {
                      "type": "number",
                      "deprecated": true,
                      "x-successor": "total_debited_money",
                      "x-sunset": "5.0.0",
                      "description": "Deprecated: floating-point monetary value (IEEE-754 binary64 cannot represent decimal minor units exactly). Use `total_debited_money` instead. Removal is scheduled for v5.0.0."
                    },
                    "currency": {
                      "type": "string",
                      "enum": [
                        "XAF",
                        "XOF",
                        "USD",
                        "EUR",
                        "GBP",
                        "CNY",
                        "NGN",
                        "GHS",
                        "KES",
                        "ZAR"
                      ],
                      "default": "XAF",
                      "description": "ISO 4217 currency code. Default is XAF (Central African CFA Franc)."
                    },
                    "status": {
                      "type": "string"
                    },
                    "beneficiary_name": {
                      "type": "string"
                    },
                    "beneficiary_account": {
                      "type": "string"
                    },
                    "tx_ref": {
                      "type": "string"
                    },
                    "created_at": {
                      "type": "string"
                    },
                    "fee_amount_money": {
                      "$ref": "#/components/schemas/Money",
                      "description": "Canonical string-encoded successor to `fee_amount`. Amount and ISO 4217 currency travel together (ISO 20022 ActiveCurrencyAndAmount). Prefer this field: it is exact for zero-decimal currencies (XAF, XOF) and immune to IEEE-754 drift.",
                      "x-added-in": "4.54.0"
                    },
                    "total_debited_money": {
                      "$ref": "#/components/schemas/Money",
                      "description": "Canonical string-encoded successor to `total_debited`. Amount and ISO 4217 currency travel together (ISO 20022 ActiveCurrencyAndAmount). Prefer this field: it is exact for zero-decimal currencies (XAF, XOF) and immune to IEEE-754 drift.",
                      "x-added-in": "4.54.0"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/gateway/withdraw-to-bank\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/gateway/withdraw-to-bank',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/gateway/withdraw-to-bank\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/gateway/withdraw-to-bank',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/banking/internal-transfer": {
      "post": {
        "tags": [
          "Banking Operations"
        ],
        "summary": "Internal account-to-account transfer",
        "description": "Transfer funds between two accounts within KOB. Validates source ownership, checks balance, creates a Debit transaction, and updates balances atomically.",
        "operationId": "bankingInternalTransfer",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "source_account_id",
                  "destination_account_id",
                  "amount"
                ],
                "properties": {
                  "source_account_id": {
                    "type": "string",
                    "format": "uuid",
                    "description": "Account to debit (must belong to authenticated user)"
                  },
                  "destination_account_id": {
                    "type": "string",
                    "format": "uuid",
                    "description": "Account to credit"
                  },
                  "amount": {
                    "type": "string",
                    "example": "25000",
                    "pattern": "^[0-9]{1,15}$",
                    "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits). Must be consistent with the currency field."
                  },
                  "currency": {
                    "type": "string",
                    "default": "XAF",
                    "enum": [
                      "XAF",
                      "XOF",
                      "USD",
                      "EUR",
                      "GBP",
                      "CNY",
                      "NGN",
                      "GHS",
                      "KES",
                      "ZAR"
                    ],
                    "description": "ISO 4217 currency code. Default is XAF (Central African CFA Franc)."
                  },
                  "reference": {
                    "type": "string",
                    "description": "Custom reference (auto-generated if omitted)"
                  },
                  "description": {
                    "type": "string",
                    "description": "Transfer narration"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Transfer completed",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "transaction_reference": {
                      "type": "string"
                    },
                    "transaction_id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "status": {
                      "type": "string",
                      "example": "Booked"
                    },
                    "amount": {
                      "type": "string",
                      "pattern": "^[0-9]{1,15}$",
                      "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits). Must be consistent with the currency field."
                    },
                    "currency": {
                      "type": "string",
                      "enum": [
                        "XAF",
                        "XOF",
                        "USD",
                        "EUR",
                        "GBP",
                        "CNY",
                        "NGN",
                        "GHS",
                        "KES",
                        "ZAR"
                      ],
                      "default": "XAF",
                      "description": "ISO 4217 currency code. Default is XAF (Central African CFA Franc)."
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/banking/internal-transfer\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/banking/internal-transfer',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/banking/internal-transfer\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/banking/internal-transfer',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/banking/facilitated-transfer": {
      "post": {
        "tags": [
          "Banking Operations"
        ],
        "summary": "Institution-facilitated bank transfer",
        "description": "Initiate a bank payout facilitated by a financial institution through the Flutterwave rail. Includes KOB fee calculation and settlement tracking. The institution_id determines fee structure and settlement bucket.",
        "operationId": "bankingFacilitatedTransfer",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "account_number",
                  "bank_code",
                  "amount",
                  "institution_id"
                ],
                "properties": {
                  "account_number": {
                    "type": "string",
                    "example": "1234567890"
                  },
                  "bank_code": {
                    "type": "string",
                    "example": "SGCM"
                  },
                  "bank_name": {
                    "type": "string",
                    "example": "Société Générale Cameroun"
                  },
                  "amount": {
                    "type": "string",
                    "example": "100000",
                    "pattern": "^[0-9]{1,15}$",
                    "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits). Must be consistent with the currency field."
                  },
                  "currency": {
                    "type": "string",
                    "default": "XAF",
                    "enum": [
                      "XAF",
                      "XOF",
                      "USD",
                      "EUR",
                      "GBP",
                      "CNY",
                      "NGN",
                      "GHS",
                      "KES",
                      "ZAR"
                    ],
                    "description": "ISO 4217 currency code. Default is XAF (Central African CFA Franc)."
                  },
                  "narration": {
                    "type": "string",
                    "example": "Salary payment"
                  },
                  "institution_id": {
                    "type": "string",
                    "format": "uuid",
                    "description": "Facilitating institution"
                  },
                  "account_name": {
                    "type": "string",
                    "example": "Jean Dupont"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Facilitated transfer initiated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "transaction_ref": {
                      "type": "string"
                    },
                    "amount": {
                      "type": "string",
                      "pattern": "^[0-9]{1,15}$",
                      "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits). Must be consistent with the currency field."
                    },
                    "kob_fee_amount": {
                      "type": "number",
                      "deprecated": true,
                      "x-successor": "kob_fee_amount_money",
                      "x-sunset": "5.0.0",
                      "description": "Deprecated: floating-point monetary value (IEEE-754 binary64 cannot represent decimal minor units exactly). Use `kob_fee_amount_money` instead. Removal is scheduled for v5.0.0."
                    },
                    "currency": {
                      "type": "string",
                      "enum": [
                        "XAF",
                        "XOF",
                        "USD",
                        "EUR",
                        "GBP",
                        "CNY",
                        "NGN",
                        "GHS",
                        "KES",
                        "ZAR"
                      ],
                      "default": "XAF",
                      "description": "ISO 4217 currency code. Default is XAF (Central African CFA Franc)."
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "pending",
                        "completed",
                        "failed"
                      ]
                    },
                    "bank_name": {
                      "type": "string"
                    },
                    "account_number": {
                      "type": "string"
                    },
                    "flutterwave_ref": {
                      "type": "string"
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "kob_fee_amount_money": {
                      "$ref": "#/components/schemas/Money",
                      "description": "Canonical string-encoded successor to `kob_fee_amount`. Amount and ISO 4217 currency travel together (ISO 20022 ActiveCurrencyAndAmount). Prefer this field: it is exact for zero-decimal currencies (XAF, XOF) and immune to IEEE-754 drift.",
                      "x-added-in": "4.54.0"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/banking/facilitated-transfer\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/banking/facilitated-transfer',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/banking/facilitated-transfer\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/banking/facilitated-transfer',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/banking/facilitated-mobile-money-charge": {
      "post": {
        "tags": [
          "Payment Facilitation"
        ],
        "summary": "Facilitated mobile money collection",
        "description": "Initiate a mobile money charge using KOB's pre-verified Flutterwave account. The institution must have use_kob_flutterwave enabled. KOB fee is automatically calculated and the transaction is tagged for settlement.",
        "operationId": "facilitatedMobileMoneyCharge",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "phone_number",
                  "amount"
                ],
                "properties": {
                  "phone_number": {
                    "type": "string",
                    "example": "237677123456",
                    "description": "Customer phone number (E.164)"
                  },
                  "amount": {
                    "type": "string",
                    "example": "5000",
                    "pattern": "^[0-9]{1,15}$",
                    "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits). Must be consistent with the currency field."
                  },
                  "currency": {
                    "type": "string",
                    "default": "XAF",
                    "enum": [
                      "XAF",
                      "XOF",
                      "USD",
                      "EUR",
                      "GBP",
                      "CNY",
                      "NGN",
                      "GHS",
                      "KES",
                      "ZAR"
                    ],
                    "description": "ISO 4217 currency code. Default is XAF (Central African CFA Franc)."
                  },
                  "email": {
                    "type": "string",
                    "example": "customer@example.com"
                  },
                  "redirect_url": {
                    "type": "string",
                    "example": "https://yoursite.com/callback"
                  },
                  "metadata": {
                    "type": "object",
                    "example": {
                      "order_id": "ORD-12345"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Mobile money charge initiated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "transaction_ref": {
                      "type": "string"
                    },
                    "transaction_id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "flutterwave_link": {
                      "type": "string",
                      "description": "Payment link for customer redirect"
                    },
                    "kob_fee_amount": {
                      "type": "number",
                      "deprecated": true,
                      "x-successor": "kob_fee_amount_money",
                      "x-sunset": "5.0.0",
                      "description": "Deprecated: floating-point monetary value (IEEE-754 binary64 cannot represent decimal minor units exactly). Use `kob_fee_amount_money` instead. Removal is scheduled for v5.0.0."
                    },
                    "net_amount": {
                      "type": "number",
                      "deprecated": true,
                      "x-successor": "net_amount_money",
                      "x-sunset": "5.0.0",
                      "description": "Deprecated: floating-point monetary value (IEEE-754 binary64 cannot represent decimal minor units exactly). Use `net_amount_money` instead. Removal is scheduled for v5.0.0."
                    },
                    "kob_fee_amount_money": {
                      "$ref": "#/components/schemas/Money",
                      "description": "Canonical string-encoded successor to `kob_fee_amount`. Amount and ISO 4217 currency travel together (ISO 20022 ActiveCurrencyAndAmount). Prefer this field: it is exact for zero-decimal currencies (XAF, XOF) and immune to IEEE-754 drift.",
                      "x-added-in": "4.54.0"
                    },
                    "net_amount_money": {
                      "$ref": "#/components/schemas/Money",
                      "description": "Canonical string-encoded successor to `net_amount`. Amount and ISO 4217 currency travel together (ISO 20022 ActiveCurrencyAndAmount). Prefer this field: it is exact for zero-decimal currencies (XAF, XOF) and immune to IEEE-754 drift.",
                      "x-added-in": "4.54.0"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "422": {
            "description": "Provider declined or upstream validation error (normalized).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "error": {
                    "$ref": "#/components/examples/ErrorUnprocessable"
                  }
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/banking/facilitated-mobile-money-charge\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/banking/facilitated-mobile-money-charge',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/banking/facilitated-mobile-money-charge\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/banking/facilitated-mobile-money-charge',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/settlement/calculate": {
      "post": {
        "tags": [
          "Payment Facilitation"
        ],
        "summary": "Calculate settlement balance",
        "description": "Calculate the settlement balance for the authenticated institution over a given period. Returns total inflows, outflows, KOB fees, and net settlement amount with a breakdown by payment method.",
        "operationId": "settlementCalculate",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "period_start": {
                    "type": "string",
                    "format": "date-time",
                    "description": "Start of period (defaults to first day of current month)"
                  },
                  "period_end": {
                    "type": "string",
                    "format": "date-time",
                    "description": "End of period (defaults to now)"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Settlement balance calculated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "institution_id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "institution_name": {
                      "type": "string"
                    },
                    "period_start": {
                      "type": "string"
                    },
                    "period_end": {
                      "type": "string"
                    },
                    "total_inflows": {
                      "type": "number",
                      "deprecated": true,
                      "x-successor": "total_inflows_money",
                      "x-sunset": "5.0.0",
                      "description": "Deprecated: floating-point monetary value (IEEE-754 binary64 cannot represent decimal minor units exactly). Use `total_inflows_money` instead. Removal is scheduled for v5.0.0."
                    },
                    "total_outflows": {
                      "type": "number",
                      "deprecated": true,
                      "x-successor": "total_outflows_money",
                      "x-sunset": "5.0.0",
                      "description": "Deprecated: floating-point monetary value (IEEE-754 binary64 cannot represent decimal minor units exactly). Use `total_outflows_money` instead. Removal is scheduled for v5.0.0."
                    },
                    "total_kob_fees": {
                      "type": "number",
                      "deprecated": true,
                      "x-successor": "total_kob_fees_money",
                      "x-sunset": "5.0.0",
                      "description": "Deprecated: floating-point monetary value (IEEE-754 binary64 cannot represent decimal minor units exactly). Use `total_kob_fees_money` instead. Removal is scheduled for v5.0.0."
                    },
                    "net_settlement_amount": {
                      "type": "number",
                      "deprecated": true,
                      "x-successor": "net_settlement_amount_money",
                      "x-sunset": "5.0.0",
                      "description": "Deprecated: floating-point monetary value (IEEE-754 binary64 cannot represent decimal minor units exactly). Use `net_settlement_amount_money` instead. Removal is scheduled for v5.0.0."
                    },
                    "transaction_count": {
                      "type": "integer"
                    },
                    "meets_minimum_threshold": {
                      "type": "boolean"
                    },
                    "can_settle": {
                      "type": "boolean"
                    },
                    "breakdown": {
                      "type": "object"
                    },
                    "total_inflows_money": {
                      "$ref": "#/components/schemas/Money",
                      "description": "Canonical string-encoded successor to `total_inflows`. Amount and ISO 4217 currency travel together (ISO 20022 ActiveCurrencyAndAmount). Prefer this field: it is exact for zero-decimal currencies (XAF, XOF) and immune to IEEE-754 drift.",
                      "x-added-in": "4.54.0"
                    },
                    "total_outflows_money": {
                      "$ref": "#/components/schemas/Money",
                      "description": "Canonical string-encoded successor to `total_outflows`. Amount and ISO 4217 currency travel together (ISO 20022 ActiveCurrencyAndAmount). Prefer this field: it is exact for zero-decimal currencies (XAF, XOF) and immune to IEEE-754 drift.",
                      "x-added-in": "4.54.0"
                    },
                    "total_kob_fees_money": {
                      "$ref": "#/components/schemas/Money",
                      "description": "Canonical string-encoded successor to `total_kob_fees`. Amount and ISO 4217 currency travel together (ISO 20022 ActiveCurrencyAndAmount). Prefer this field: it is exact for zero-decimal currencies (XAF, XOF) and immune to IEEE-754 drift.",
                      "x-added-in": "4.54.0"
                    },
                    "net_settlement_amount_money": {
                      "$ref": "#/components/schemas/Money",
                      "description": "Canonical string-encoded successor to `net_settlement_amount`. Amount and ISO 4217 currency travel together (ISO 20022 ActiveCurrencyAndAmount). Prefer this field: it is exact for zero-decimal currencies (XAF, XOF) and immune to IEEE-754 drift.",
                      "x-added-in": "4.54.0"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/settlement/calculate\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/settlement/calculate',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/settlement/calculate\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/settlement/calculate',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/settlement/process": {
      "post": {
        "tags": [
          "Payment Facilitation"
        ],
        "summary": "Process settlement payout",
        "description": "Process a settlement payout for a facilitated institution. Admin-only. Debits the net settlement amount and transfers to the institution's configured bank or mobile money account via Flutterwave.",
        "operationId": "settlementProcess",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "institution_id",
                  "period_start",
                  "period_end"
                ],
                "properties": {
                  "institution_id": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "period_start": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "period_end": {
                    "type": "string",
                    "format": "date-time"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Settlement processed",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "settlement_id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "settlement_ref": {
                      "type": "string"
                    },
                    "net_amount": {
                      "type": "number",
                      "deprecated": true,
                      "x-successor": "net_amount_money",
                      "x-sunset": "5.0.0",
                      "description": "Deprecated: floating-point monetary value (IEEE-754 binary64 cannot represent decimal minor units exactly). Use `net_amount_money` instead. Removal is scheduled for v5.0.0."
                    },
                    "flutterwave_transfer_id": {
                      "type": "integer"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "processing",
                        "completed",
                        "failed"
                      ]
                    },
                    "net_amount_money": {
                      "$ref": "#/components/schemas/Money",
                      "description": "Canonical string-encoded successor to `net_amount`. Amount and ISO 4217 currency travel together (ISO 20022 ActiveCurrencyAndAmount). Prefer this field: it is exact for zero-decimal currencies (XAF, XOF) and immune to IEEE-754 drift.",
                      "x-added-in": "4.54.0"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/settlement/process\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/settlement/process',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/settlement/process\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/settlement/process',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/gateway/risk/score": {
      "post": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "Score transaction risk",
        "description": "Run velocity, amount-threshold, and pattern-anomaly checks against a proposed transaction. Returns a 0–100 risk score, flags, and recommended action (allow | flag_for_review | block).",
        "operationId": "gatewayRiskScore",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "merchant_id",
                  "amount",
                  "channel"
                ],
                "properties": {
                  "merchant_id": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "amount": {
                    "type": "string",
                    "example": "500000",
                    "pattern": "^[0-9]{1,15}$",
                    "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits). Must be consistent with the currency field."
                  },
                  "currency": {
                    "type": "string",
                    "default": "XAF",
                    "enum": [
                      "XAF",
                      "XOF",
                      "USD",
                      "EUR",
                      "GBP",
                      "CNY",
                      "NGN",
                      "GHS",
                      "KES",
                      "ZAR"
                    ],
                    "description": "ISO 4217 currency code. Default is XAF (Central African CFA Franc)."
                  },
                  "channel": {
                    "type": "string",
                    "enum": [
                      "mobile_money",
                      "card",
                      "bank_transfer",
                      "ussd"
                    ]
                  },
                  "customer_email": {
                    "type": "string"
                  },
                  "customer_phone": {
                    "type": "string"
                  },
                  "customer_ip": {
                    "type": "string"
                  },
                  "metadata": {
                    "type": "object"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Risk assessment result",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "risk_score": {
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 100,
                      "example": 35
                    },
                    "risk_level": {
                      "type": "string",
                      "enum": [
                        "low",
                        "medium",
                        "high",
                        "critical"
                      ]
                    },
                    "flags": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "example": [
                        "high_amount"
                      ]
                    },
                    "recommended_action": {
                      "type": "string",
                      "enum": [
                        "allow",
                        "flag_for_review",
                        "block"
                      ]
                    },
                    "checks": {
                      "type": "object",
                      "properties": {
                        "velocity": {
                          "type": "object",
                          "properties": {
                            "passed": {
                              "type": "boolean"
                            },
                            "tx_count_1h": {
                              "type": "integer"
                            },
                            "limit": {
                              "type": "integer"
                            }
                          }
                        },
                        "amount_threshold": {
                          "type": "object",
                          "properties": {
                            "passed": {
                              "type": "boolean"
                            },
                            "threshold": {
                              "type": "number"
                            }
                          }
                        },
                        "pattern_anomaly": {
                          "type": "object",
                          "properties": {
                            "passed": {
                              "type": "boolean"
                            },
                            "anomaly_type": {
                              "type": "string"
                            }
                          }
                        }
                      }
                    },
                    "evaluated_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Recommended for safe retries. UUID v4. When supplied, duplicate requests within 24h replay the original response. See Idempotency guide."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/gateway/risk/score\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/gateway/risk/score',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/gateway/risk/score\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/gateway/risk/score',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/gateway/exchange-rate": {
      "get": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "Get exchange rate",
        "description": "Look up real-time exchange rates for multi-currency charges and settlements. Powered by Frankfurter API.",
        "operationId": "gatewayExchangeRate",
        "security": [],
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "example": "XAF"
            },
            "description": "Source currency (ISO 4217)"
          },
          {
            "name": "to",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "example": "USD"
            },
            "description": "Target currency (ISO 4217)"
          },
          {
            "name": "amount",
            "in": "query",
            "schema": {
              "type": "number",
              "default": 1
            },
            "description": "Amount to convert"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Exchange rate result",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "from": {
                      "type": "string",
                      "example": "XAF"
                    },
                    "to": {
                      "type": "string",
                      "example": "USD"
                    },
                    "rate": {
                      "type": "number",
                      "example": 0.0016
                    },
                    "amount": {
                      "type": "string",
                      "example": "100000",
                      "pattern": "^[0-9]{1,15}$",
                      "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits)."
                    },
                    "converted": {
                      "type": "number",
                      "example": 160
                    },
                    "timestamp": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "source": {
                      "type": "string",
                      "example": "frankfurter"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/gateway/exchange-rate\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/gateway/exchange-rate',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/gateway/exchange-rate\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/gateway/exchange-rate',\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/gateway/payment-links": {
      "post": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "Create payment link",
        "operationId": "gatewayCreatePaymentLink",
        "security": [
          {
            "bearerAuth": []
          },
          {
            "MerchantSecretKey": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "merchant_id",
                  "name",
                  "amount"
                ],
                "properties": {
                  "merchant_id": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "name": {
                    "type": "string"
                  },
                  "amount": {
                    "type": "string",
                    "pattern": "^[0-9]{1,15}$",
                    "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits). Must be consistent with the currency field."
                  },
                  "currency": {
                    "type": "string",
                    "default": "XAF",
                    "enum": [
                      "XAF",
                      "XOF",
                      "USD",
                      "EUR",
                      "GBP",
                      "CNY",
                      "NGN",
                      "GHS",
                      "KES",
                      "ZAR"
                    ],
                    "description": "ISO 4217 currency code. Default is XAF (Central African CFA Franc)."
                  },
                  "redirect_url": {
                    "type": "string"
                  },
                  "max_uses": {
                    "type": "integer"
                  },
                  "expires_at": {
                    "type": "string",
                    "format": "date-time"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Payment link created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewayPaymentLink"
                },
                "examples": {
                  "default": {
                    "summary": "Payment intent created",
                    "value": {
                      "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                      "merchant_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                      "name": "Product Payment",
                      "slug": "product-payment-abc123",
                      "amount": "5000",
                      "currency": "XAF",
                      "status": "active",
                      "success": true,
                      "data": {
                        "id": "pi_01HZX9TRJ4M7YQK6P3W2VBDN5K",
                        "object": "payment_intent",
                        "amount": "5000",
                        "currency": "XAF",
                        "status": "requires_confirmation",
                        "client_secret": "pi_01HZX9TRJ4M7YQK6P3W2VBDN5K_secret_aBc123",
                        "payment_method_types": [
                          "mobile_money",
                          "card",
                          "bank_transfer"
                        ],
                        "idempotency_key": "550e8400-e29b-41d4-a716-446655440000",
                        "created_at": "2026-05-02T10:15:30Z"
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      }
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Create payment link.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/gateway/payment-links\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/gateway/payment-links',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/gateway/payment-links\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/gateway/payment-links',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      },
      "get": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "List payment links",
        "operationId": "gatewayListPaymentLinks",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "merchant_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "slug",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 25,
              "maximum": 100,
              "minimum": 1
            },
            "description": "Items per page"
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 0
            },
            "description": "Items to skip"
          },
          {
            "name": "sort_by",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "created_at"
            },
            "description": "Sort field"
          },
          {
            "name": "sort_order",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "asc",
                "desc"
              ],
              "default": "desc"
            },
            "description": "Sort direction"
          },
          {
            "$ref": "#/components/parameters/StartingAfter"
          },
          {
            "$ref": "#/components/parameters/EndingBefore"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          },
          {
            "$ref": "#/components/parameters/CursorParam"
          }
        ],
        "responses": {
          "200": {
            "description": "Payment links",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/GatewayPaymentLink"
                          }
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Payment intent created",
                    "value": {
                      "data": [
                        {
                          "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "merchant_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "name": "Product Payment",
                          "slug": "product-payment-abc123",
                          "amount": "5000",
                          "currency": "XAF",
                          "status": "active"
                        }
                      ],
                      "pagination": {
                        "page": 1,
                        "limit": 20,
                        "total": 150,
                        "has_next": true
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              },
              "X-Pagination-Mode": {
                "description": "Pagination mode used for this response (always `cursor` for d.2A operations).",
                "schema": {
                  "type": "string",
                  "enum": [
                    "cursor"
                  ]
                }
              },
              "X-Pagination-Has-More": {
                "description": "Boolean flag (`true`/`false`) indicating whether more pages are available.",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true",
                    "false"
                  ]
                }
              },
              "X-Pagination-Next-Cursor": {
                "description": "Opaque continuation cursor. Omitted when has_more is false.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Pagination-Limit": {
                "description": "Effective per-page limit used for this response.",
                "schema": {
                  "type": "integer",
                  "minimum": 1,
                  "maximum": 100
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "List payment links.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/gateway/payment-links\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/gateway/payment-links',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/gateway/payment-links\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/gateway/payment-links',\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/gateway/payment-links/{linkId}": {
      "put": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "Update payment link",
        "operationId": "gatewayUpdatePaymentLink",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "linkId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "amount": {
                    "type": "string",
                    "pattern": "^[0-9]{1,15}$",
                    "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits)."
                  },
                  "status": {
                    "type": "string"
                  },
                  "redirect_url": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Payment link updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewayPaymentLink"
                },
                "examples": {
                  "default": {
                    "summary": "Payment intent created",
                    "value": {
                      "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                      "merchant_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                      "name": "Product Payment",
                      "slug": "product-payment-abc123",
                      "amount": "5000",
                      "currency": "XAF",
                      "status": "active",
                      "success": true,
                      "data": {
                        "id": "pi_01HZX9TRJ4M7YQK6P3W2VBDN5K",
                        "object": "payment_intent",
                        "amount": "5000",
                        "currency": "XAF",
                        "status": "requires_confirmation",
                        "client_secret": "pi_01HZX9TRJ4M7YQK6P3W2VBDN5K_secret_aBc123",
                        "payment_method_types": [
                          "mobile_money",
                          "card",
                          "bank_transfer"
                        ],
                        "idempotency_key": "550e8400-e29b-41d4-a716-446655440000",
                        "created_at": "2026-05-02T10:15:30Z"
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      }
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Update payment link.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X PUT \"https://api.kangopenbanking.com/v1/gateway/payment-links/{linkId}\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'PUT',\n  path: '/v1/gateway/payment-links/{linkId}',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"PUT\",\n    path=\"/v1/gateway/payment-links/{linkId}\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'PUT',\n    'path'   => '/v1/gateway/payment-links/{linkId}',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      },
      "delete": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "Delete payment link",
        "operationId": "gatewayDeletePaymentLink",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "linkId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "204": {
            "description": "Payment link deleted",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            },
            "content": {
              "application/json": {
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/PaymentIntentCreated"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Delete payment link.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X DELETE \"https://api.kangopenbanking.com/v1/gateway/payment-links/{linkId}\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'DELETE',\n  path: '/v1/gateway/payment-links/{linkId}',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"DELETE\",\n    path=\"/v1/gateway/payment-links/{linkId}\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'DELETE',\n    'path'   => '/v1/gateway/payment-links/{linkId}',\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/gateway/payment-plans": {
      "post": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "Create payment plan",
        "operationId": "gatewayCreatePaymentPlan",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "merchant_id",
                  "name",
                  "amount",
                  "interval"
                ],
                "properties": {
                  "merchant_id": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "name": {
                    "type": "string"
                  },
                  "amount": {
                    "type": "string",
                    "pattern": "^[0-9]{1,15}$",
                    "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits). Must be consistent with the currency field."
                  },
                  "currency": {
                    "type": "string",
                    "default": "XAF",
                    "enum": [
                      "XAF",
                      "XOF",
                      "USD",
                      "EUR",
                      "GBP",
                      "CNY",
                      "NGN",
                      "GHS",
                      "KES",
                      "ZAR"
                    ],
                    "description": "ISO 4217 currency code. Default is XAF (Central African CFA Franc)."
                  },
                  "interval": {
                    "type": "string",
                    "enum": [
                      "daily",
                      "weekly",
                      "monthly",
                      "quarterly",
                      "yearly"
                    ]
                  },
                  "duration": {
                    "type": "integer"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Plan created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewayPaymentPlan"
                },
                "examples": {
                  "default": {
                    "summary": "Payment intent created",
                    "value": {
                      "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                      "merchant_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                      "name": "Monthly Pro Plan",
                      "amount": "10000",
                      "currency": "XAF",
                      "success": true,
                      "data": {
                        "id": "pi_01HZX9TRJ4M7YQK6P3W2VBDN5K",
                        "object": "payment_intent",
                        "amount": "5000",
                        "currency": "XAF",
                        "status": "requires_confirmation",
                        "client_secret": "pi_01HZX9TRJ4M7YQK6P3W2VBDN5K_secret_aBc123",
                        "payment_method_types": [
                          "mobile_money",
                          "card",
                          "bank_transfer"
                        ],
                        "idempotency_key": "550e8400-e29b-41d4-a716-446655440000",
                        "created_at": "2026-05-02T10:15:30Z"
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      }
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Create payment plan.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/gateway/payment-plans\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/gateway/payment-plans',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/gateway/payment-plans\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/gateway/payment-plans',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      },
      "get": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "List payment plans",
        "operationId": "gatewayListPaymentPlans",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "merchant_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Number of items per page. Defaults to 25. Maximum 100. Minimum 1.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 25,
              "example": 25
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "deprecated": true,
            "description": "Deprecated. Retained for legacy initial-page compatibility. Used only when no cursor is supplied. Values greater than zero produce hybrid mode: the first page is offset-based but the response returns a signed continuation cursor for subsequent pages. Once a valid cursor is supplied, offset is ignored. No exact total is calculated. Clients should migrate to cursor.",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          },
          {
            "name": "sort_by",
            "in": "query",
            "required": false,
            "description": "Sort field. Deterministic ordering is `created_at DESC, id DESC`; the UUID `id` is the unique final tie-breaker.",
            "schema": {
              "type": "string",
              "enum": [
                "created_at"
              ],
              "default": "created_at"
            }
          },
          {
            "name": "sort_order",
            "in": "query",
            "required": false,
            "description": "Sort direction. Only descending is supported for cursor pagination.",
            "schema": {
              "type": "string",
              "enum": [
                "desc"
              ],
              "default": "desc"
            }
          },
          {
            "name": "starting_after",
            "in": "query",
            "required": false,
            "deprecated": true,
            "description": "Deprecated cursor alias. Only opaque KOB continuation tokens are recognised; arbitrary database identifiers are not interpreted as cursors. Represents the same forward continuation semantics as `cursor`. Supplying multiple distinct cursor values across `cursor`, `starting_after`, and `ending_before` returns HTTP 400 (`PAGINATION_CURSOR_INVALID`).",
            "schema": {
              "type": "string",
              "maxLength": 512
            }
          },
          {
            "name": "ending_before",
            "in": "query",
            "required": false,
            "deprecated": true,
            "description": "Deprecated cursor alias. Only opaque KOB continuation tokens are recognised; arbitrary database identifiers are not interpreted as cursors. Represents the same forward continuation semantics as `cursor` and does NOT provide backward pagination. Supplying multiple distinct cursor values across `cursor`, `starting_after`, and `ending_before` returns HTTP 400 (`PAGINATION_CURSOR_INVALID`).",
            "schema": {
              "type": "string",
              "maxLength": 512
            }
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          },
          {
            "$ref": "#/components/parameters/CursorParam"
          }
        ],
        "responses": {
          "200": {
            "description": "Payment plans",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/GatewayPaymentPlan"
                          }
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Payment intent created",
                    "value": {
                      "data": [
                        {
                          "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "merchant_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "name": "Monthly Pro Plan",
                          "amount": "10000",
                          "currency": "XAF"
                        }
                      ],
                      "pagination": {
                        "page": 1,
                        "limit": 20,
                        "total": 150,
                        "has_next": true
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              },
              "X-Pagination-Mode": {
                "description": "Pagination mode used for this response. `cursor` when a signed cursor drove the query; `hybrid` when a legacy `offset` seeded the first page and a signed continuation cursor is returned.",
                "schema": {
                  "type": "string",
                  "enum": [
                    "cursor",
                    "hybrid"
                  ]
                }
              },
              "X-Pagination-Has-More": {
                "description": "Boolean flag indicating whether more pages are available.",
                "schema": {
                  "type": "boolean"
                }
              },
              "X-Pagination-Next-Cursor": {
                "description": "Opaque KOB-signed continuation cursor. An empty header value means no continuation exists.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Pagination-Limit": {
                "description": "Effective per-page limit used for this response.",
                "schema": {
                  "type": "integer",
                  "minimum": 1,
                  "maximum": 100
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "List payment plans.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.\n\nPagination:\n- Default page size: 25 (`limit`, maximum 100, minimum 1).\n- Cursor is the preferred continuation mechanism. Continuation cursors are opaque KOB-signed tokens with a lifetime of 1800 seconds. Each cursor is bound to the authenticated actor, merchant, environment, and operation; changing a bound filter invalidates the cursor and returns `PAGINATION_CURSOR_FILTER_MISMATCH`.\n- `offset` is deprecated and retained for legacy initial-page compatibility. When `offset > 0` is supplied without a cursor, responses use hybrid mode and return a signed continuation cursor for subsequent pages; once a cursor is present, offset is ignored. No exact total is returned.\n- `starting_after` and `ending_before` are deprecated cursor aliases. Only opaque KOB cursor tokens are accepted. Both represent the same forward continuation semantics; `ending_before` does not provide backward pagination. Supplying multiple distinct cursor values returns HTTP 400.\n- Deterministic ordering: `created_at DESC, id DESC` (the UUID `id` is the final tie-breaker).\n- Successful responses use the `{data, pagination, meta}` envelope. The four response headers `X-Pagination-Mode`, `X-Pagination-Has-More`, `X-Pagination-Next-Cursor`, and `X-Pagination-Limit` mirror the body pagination state.\n\nPagination error codes (HTTP 400 Problem Details): `PAGINATION_LIMIT_INVALID`, `PAGINATION_CURSOR_INVALID`, `PAGINATION_CURSOR_EXPIRED`, `PAGINATION_CURSOR_OPERATION_MISMATCH`, `PAGINATION_CURSOR_SCOPE_MISMATCH`, `PAGINATION_CURSOR_FILTER_MISMATCH`.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/gateway/payment-plans\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/gateway/payment-plans',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/gateway/payment-plans\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/gateway/payment-plans',\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/gateway/payment-plans/{planId}": {
      "get": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "Get payment plan",
        "operationId": "gatewayGetPaymentPlan",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "planId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Plan details",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/StandardResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/GatewayPaymentPlan"
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Payment intent created",
                    "value": {
                      "data": {
                        "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                        "merchant_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                        "name": "Monthly Pro Plan",
                        "amount": "5000",
                        "currency": "XAF",
                        "object": "payment_intent",
                        "client_secret": "pi_01HZX9TRJ4M7YQK6P3W2VBDN5K_secret_aBc123",
                        "payment_method_types": [
                          "mobile_money",
                          "card",
                          "bank_transfer"
                        ],
                        "idempotency_key": "550e8400-e29b-41d4-a716-446655440000",
                        "created_at": "2026-05-02T10:15:30Z"
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Get payment plan.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/gateway/payment-plans/{planId}\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/gateway/payment-plans/{planId}',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/gateway/payment-plans/{planId}\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/gateway/payment-plans/{planId}',\n]);\n\nprint_r($response->data);"
          }
        ]
      },
      "put": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "Update payment plan",
        "operationId": "gatewayUpdatePaymentPlan",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "planId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Recommended for safe retries. UUID v4. When supplied, duplicate requests within 24h replay the original response. See Idempotency guide."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "amount": {
                    "type": "string",
                    "pattern": "^[0-9]{1,15}$",
                    "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits)."
                  },
                  "status": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Plan updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewayPaymentPlan"
                },
                "examples": {
                  "default": {
                    "summary": "Payment intent created",
                    "value": {
                      "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                      "merchant_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                      "name": "Monthly Pro Plan",
                      "amount": "10000",
                      "currency": "XAF",
                      "success": true,
                      "data": {
                        "id": "pi_01HZX9TRJ4M7YQK6P3W2VBDN5K",
                        "object": "payment_intent",
                        "amount": "5000",
                        "currency": "XAF",
                        "status": "requires_confirmation",
                        "client_secret": "pi_01HZX9TRJ4M7YQK6P3W2VBDN5K_secret_aBc123",
                        "payment_method_types": [
                          "mobile_money",
                          "card",
                          "bank_transfer"
                        ],
                        "idempotency_key": "550e8400-e29b-41d4-a716-446655440000",
                        "created_at": "2026-05-02T10:15:30Z"
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      }
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Update payment plan.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X PUT \"https://api.kangopenbanking.com/v1/gateway/payment-plans/{planId}\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'PUT',\n  path: '/v1/gateway/payment-plans/{planId}',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"PUT\",\n    path=\"/v1/gateway/payment-plans/{planId}\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'PUT',\n    'path'   => '/v1/gateway/payment-plans/{planId}',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/gateway/subscriptions": {
      "post": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "Create subscription",
        "operationId": "gatewayCreateSubscription",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "plan_id",
                  "customer_email"
                ],
                "properties": {
                  "plan_id": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "customer_email": {
                    "type": "string"
                  },
                  "customer_phone": {
                    "type": "string"
                  },
                  "token_id": {
                    "type": "string",
                    "description": "Saved payment token for recurring charges"
                  },
                  "metadata": {
                    "type": "object"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Subscription created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewaySubscription"
                },
                "examples": {
                  "default": {
                    "summary": "Successful response envelope",
                    "value": {
                      "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                      "plan_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                      "status": "active",
                      "current_period_start": "2026-05-02T10:15:30Z",
                      "current_period_end": "2026-05-02T10:15:30Z",
                      "created_at": "2026-05-02T10:15:30Z",
                      "success": true,
                      "data": {
                        "id": "obj_01HZX9TRJ4M7YQK6P3W2VBDN5K",
                        "object": "resource",
                        "created_at": "2026-05-02T10:15:30Z"
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      }
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Create subscription.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/gateway/subscriptions\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/gateway/subscriptions',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/gateway/subscriptions\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/gateway/subscriptions',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      },
      "get": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "List subscriptions",
        "operationId": "gatewayListSubscriptions",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "plan_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Number of items per page. Defaults to 25. Maximum 100. Minimum 1.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 25,
              "example": 25
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "deprecated": true,
            "description": "Deprecated. Retained for legacy initial-page compatibility. Used only when no cursor is supplied. Values greater than zero produce hybrid mode: the first page is offset-based but the response returns a signed continuation cursor for subsequent pages. Once a valid cursor is supplied, offset is ignored. No exact total is calculated. Clients should migrate to cursor.",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          },
          {
            "name": "sort_by",
            "in": "query",
            "required": false,
            "description": "Sort field. Deterministic ordering is `created_at DESC, id DESC`; the UUID `id` is the unique final tie-breaker.",
            "schema": {
              "type": "string",
              "enum": [
                "created_at"
              ],
              "default": "created_at"
            }
          },
          {
            "name": "sort_order",
            "in": "query",
            "required": false,
            "description": "Sort direction. Only descending is supported for cursor pagination.",
            "schema": {
              "type": "string",
              "enum": [
                "desc"
              ],
              "default": "desc"
            }
          },
          {
            "name": "starting_after",
            "in": "query",
            "required": false,
            "deprecated": true,
            "description": "Deprecated cursor alias. Only opaque KOB continuation tokens are recognised; arbitrary database identifiers are not interpreted as cursors. Represents the same forward continuation semantics as `cursor`. Supplying multiple distinct cursor values across `cursor`, `starting_after`, and `ending_before` returns HTTP 400 (`PAGINATION_CURSOR_INVALID`).",
            "schema": {
              "type": "string",
              "maxLength": 512
            }
          },
          {
            "name": "ending_before",
            "in": "query",
            "required": false,
            "deprecated": true,
            "description": "Deprecated cursor alias. Only opaque KOB continuation tokens are recognised; arbitrary database identifiers are not interpreted as cursors. Represents the same forward continuation semantics as `cursor` and does NOT provide backward pagination. Supplying multiple distinct cursor values across `cursor`, `starting_after`, and `ending_before` returns HTTP 400 (`PAGINATION_CURSOR_INVALID`).",
            "schema": {
              "type": "string",
              "maxLength": 512
            }
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          },
          {
            "$ref": "#/components/parameters/CursorParam"
          }
        ],
        "responses": {
          "200": {
            "description": "Subscriptions",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/GatewaySubscription"
                          }
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Cursor-paginated list",
                    "value": {
                      "data": [
                        {
                          "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "plan_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "status": "active",
                          "current_period_start": "2026-05-02T10:15:30Z",
                          "current_period_end": "2026-05-02T10:15:30Z",
                          "created_at": "2026-05-02T10:15:30Z",
                          "object": "resource"
                        },
                        {
                          "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "plan_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "status": "active",
                          "current_period_start": "2026-05-02T10:15:30Z",
                          "current_period_end": "2026-05-02T10:15:30Z",
                          "created_at": "2026-05-02T10:15:31Z",
                          "object": "resource"
                        }
                      ],
                      "pagination": {
                        "page": 1,
                        "limit": 20,
                        "total": 150,
                        "has_next": true,
                        "has_more": true,
                        "next_cursor": "cursor_01HZX9TRJ4M7YQK6P3W2VBDN5M",
                        "prev_cursor": null,
                        "total_count": 247
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              },
              "X-Pagination-Mode": {
                "description": "Pagination mode used for this response. `cursor` when a signed cursor drove the query; `hybrid` when a legacy `offset` seeded the first page and a signed continuation cursor is returned.",
                "schema": {
                  "type": "string",
                  "enum": [
                    "cursor",
                    "hybrid"
                  ]
                }
              },
              "X-Pagination-Has-More": {
                "description": "Boolean flag indicating whether more pages are available.",
                "schema": {
                  "type": "boolean"
                }
              },
              "X-Pagination-Next-Cursor": {
                "description": "Opaque KOB-signed continuation cursor. An empty header value means no continuation exists.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Pagination-Limit": {
                "description": "Effective per-page limit used for this response.",
                "schema": {
                  "type": "integer",
                  "minimum": 1,
                  "maximum": 100
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "List subscriptions.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.\n\nPagination:\n- Default page size: 25 (`limit`, maximum 100, minimum 1).\n- Cursor is the preferred continuation mechanism. Continuation cursors are opaque KOB-signed tokens with a lifetime of 1800 seconds. Each cursor is bound to the authenticated actor, merchant, environment, and operation; changing a bound filter invalidates the cursor and returns `PAGINATION_CURSOR_FILTER_MISMATCH`.\n- `offset` is deprecated and retained for legacy initial-page compatibility. When `offset > 0` is supplied without a cursor, responses use hybrid mode and return a signed continuation cursor for subsequent pages; once a cursor is present, offset is ignored. No exact total is returned.\n- `starting_after` and `ending_before` are deprecated cursor aliases. Only opaque KOB cursor tokens are accepted. Both represent the same forward continuation semantics; `ending_before` does not provide backward pagination. Supplying multiple distinct cursor values returns HTTP 400.\n- Deterministic ordering: `created_at DESC, id DESC` (the UUID `id` is the final tie-breaker).\n- Successful responses use the `{data, pagination, meta}` envelope. The four response headers `X-Pagination-Mode`, `X-Pagination-Has-More`, `X-Pagination-Next-Cursor`, and `X-Pagination-Limit` mirror the body pagination state.\n- Filter binding for cursor continuation: `plan_id` and `status` are bound to the cursor. Changing either while continuing a cursor returns `PAGINATION_CURSOR_FILTER_MISMATCH`.\n\nPagination error codes (HTTP 400 Problem Details): `PAGINATION_LIMIT_INVALID`, `PAGINATION_CURSOR_INVALID`, `PAGINATION_CURSOR_EXPIRED`, `PAGINATION_CURSOR_OPERATION_MISMATCH`, `PAGINATION_CURSOR_SCOPE_MISMATCH`, `PAGINATION_CURSOR_FILTER_MISMATCH`.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/gateway/subscriptions\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/gateway/subscriptions',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/gateway/subscriptions\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/gateway/subscriptions',\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/gateway/subscriptions/{subscriptionId}": {
      "get": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "Get subscription",
        "operationId": "gatewayGetSubscription",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "subscriptionId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Subscription details",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/StandardResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/GatewaySubscription"
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Successful response envelope",
                    "value": {
                      "data": {
                        "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                        "plan_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                        "status": "active",
                        "current_period_start": "2026-05-02T10:15:30Z",
                        "current_period_end": "2026-05-02T10:15:30Z",
                        "created_at": "2026-05-02T10:15:30Z",
                        "object": "resource"
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Get subscription.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/gateway/subscriptions/{subscriptionId}\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/gateway/subscriptions/{subscriptionId}',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/gateway/subscriptions/{subscriptionId}\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/gateway/subscriptions/{subscriptionId}',\n]);\n\nprint_r($response->data);"
          }
        ]
      },
      "patch": {
        "operationId": "updateSubscription",
        "summary": "Update a subscription",
        "description": "Update an existing subscription (e.g. change plan, billing cycle, or metadata). Only non-terminated subscriptions can be updated.",
        "tags": [
          "Payment Gateway"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "subscriptionId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Subscription unique identifier"
          },
          {
            "$ref": "#/components/parameters/XFapiInteractionId"
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Recommended for safe retries. UUID v4. When supplied, duplicate requests within 24h replay the original response. See Idempotency guide."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "plan_id": {
                    "type": "string",
                    "description": "New plan identifier to switch to"
                  },
                  "metadata": {
                    "type": "object",
                    "additionalProperties": {
                      "type": "string"
                    }
                  },
                  "billing_cycle_anchor": {
                    "type": "string",
                    "format": "date-time",
                    "description": "New billing cycle anchor date"
                  },
                  "proration_behavior": {
                    "type": "string",
                    "enum": [
                      "create_prorations",
                      "none",
                      "always_invoice"
                    ],
                    "default": "create_prorations"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Subscription updated successfully",
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewaySubscription"
                },
                "examples": {
                  "default": {
                    "summary": "Successful response envelope",
                    "value": {
                      "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                      "plan_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                      "status": "active",
                      "current_period_start": "2026-05-02T10:15:30Z",
                      "current_period_end": "2026-05-02T10:15:30Z",
                      "created_at": "2026-05-02T10:15:30Z",
                      "success": true,
                      "data": {
                        "id": "obj_01HZX9TRJ4M7YQK6P3W2VBDN5K",
                        "object": "resource",
                        "created_at": "2026-05-02T10:15:30Z"
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorised",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Subscription not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "$ref": "#/components/responses/Conflict",
            "headers": {
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X PATCH \"https://api.kangopenbanking.com/v1/gateway/subscriptions/{subscriptionId}\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'PATCH',\n  path: '/v1/gateway/subscriptions/{subscriptionId}',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"PATCH\",\n    path=\"/v1/gateway/subscriptions/{subscriptionId}\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'PATCH',\n    'path'   => '/v1/gateway/subscriptions/{subscriptionId}',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      },
      "delete": {
        "operationId": "deleteSubscription",
        "summary": "Cancel a subscription",
        "description": "Cancel (soft-delete) a subscription. The subscription will complete its current billing period unless cancel_immediately is true.",
        "tags": [
          "Payment Gateway"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "subscriptionId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Subscription unique identifier"
          },
          {
            "name": "cancel_immediately",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false
            },
            "description": "If true, cancel immediately without finishing the current period"
          },
          {
            "$ref": "#/components/parameters/XFapiInteractionId"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Subscription cancelled successfully",
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewaySubscription"
                },
                "examples": {
                  "default": {
                    "summary": "Successful response envelope",
                    "value": {
                      "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                      "plan_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                      "status": "active",
                      "current_period_start": "2026-05-02T10:15:30Z",
                      "current_period_end": "2026-05-02T10:15:30Z",
                      "created_at": "2026-05-02T10:15:30Z",
                      "success": true,
                      "data": {
                        "id": "obj_01HZX9TRJ4M7YQK6P3W2VBDN5K",
                        "object": "resource",
                        "created_at": "2026-05-02T10:15:30Z"
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request — validation failed or malformed input.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          },
          "401": {
            "description": "Unauthorised",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Subscription not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "$ref": "#/components/responses/Conflict",
            "headers": {
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X DELETE \"https://api.kangopenbanking.com/v1/gateway/subscriptions/{subscriptionId}\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'DELETE',\n  path: '/v1/gateway/subscriptions/{subscriptionId}',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"DELETE\",\n    path=\"/v1/gateway/subscriptions/{subscriptionId}\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'DELETE',\n    'path'   => '/v1/gateway/subscriptions/{subscriptionId}',\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/gateway/subscriptions/cancel": {
      "post": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "Cancel subscription",
        "operationId": "gatewayCancelSubscription",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "subscription_id"
                ],
                "properties": {
                  "subscription_id": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "reason": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Subscription cancelled",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewaySubscription"
                },
                "examples": {
                  "default": {
                    "summary": "Successful response envelope",
                    "value": {
                      "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                      "plan_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                      "status": "active",
                      "current_period_start": "2026-05-02T10:15:30Z",
                      "current_period_end": "2026-05-02T10:15:30Z",
                      "created_at": "2026-05-02T10:15:30Z",
                      "success": true,
                      "data": {
                        "id": "obj_01HZX9TRJ4M7YQK6P3W2VBDN5K",
                        "object": "resource",
                        "created_at": "2026-05-02T10:15:30Z"
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      }
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "description": "Cancel subscription.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/gateway/subscriptions/cancel\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/gateway/subscriptions/cancel',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/gateway/subscriptions/cancel\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/gateway/subscriptions/cancel',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/gateway/subaccounts": {
      "post": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "Create subaccount",
        "operationId": "gatewayCreateSubaccount",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "merchant_id",
                  "business_name",
                  "settlement_bank",
                  "account_number"
                ],
                "properties": {
                  "merchant_id": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "business_name": {
                    "type": "string"
                  },
                  "settlement_bank": {
                    "type": "string"
                  },
                  "account_number": {
                    "type": "string"
                  },
                  "split_type": {
                    "type": "string",
                    "enum": [
                      "percentage",
                      "flat"
                    ]
                  },
                  "split_value": {
                    "type": "number"
                  },
                  "country": {
                    "type": "string",
                    "default": "CM"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Subaccount created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewaySubaccount"
                },
                "examples": {
                  "default": {
                    "summary": "Successful response envelope",
                    "value": {
                      "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                      "merchant_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                      "business_name": "business_name_value",
                      "account_number": "account_number_value",
                      "success": true,
                      "data": {
                        "id": "obj_01HZX9TRJ4M7YQK6P3W2VBDN5K",
                        "object": "resource",
                        "created_at": "2026-05-02T10:15:30Z"
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      }
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Create subaccount.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/gateway/subaccounts\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/gateway/subaccounts',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/gateway/subaccounts\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/gateway/subaccounts',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      },
      "get": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "List subaccounts",
        "operationId": "gatewayListSubaccounts",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "merchant_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 25,
              "maximum": 100,
              "minimum": 1
            },
            "description": "Items per page"
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 0
            },
            "description": "Items to skip"
          },
          {
            "name": "sort_by",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "created_at"
            },
            "description": "Sort field"
          },
          {
            "name": "sort_order",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "asc",
                "desc"
              ],
              "default": "desc"
            },
            "description": "Sort direction"
          },
          {
            "$ref": "#/components/parameters/StartingAfter"
          },
          {
            "$ref": "#/components/parameters/EndingBefore"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          },
          {
            "$ref": "#/components/parameters/CursorParam"
          }
        ],
        "responses": {
          "200": {
            "description": "Subaccounts",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/GatewaySubaccount"
                          }
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Cursor-paginated list",
                    "value": {
                      "data": [
                        {
                          "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "merchant_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "business_name": "business_name_value",
                          "account_number": "account_number_value",
                          "object": "resource",
                          "created_at": "2026-05-02T10:15:30Z"
                        },
                        {
                          "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "merchant_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "business_name": "business_name_value",
                          "account_number": "account_number_value",
                          "object": "resource",
                          "created_at": "2026-05-02T10:15:31Z"
                        }
                      ],
                      "pagination": {
                        "page": 1,
                        "limit": 20,
                        "total": 150,
                        "has_next": true,
                        "has_more": true,
                        "next_cursor": "cursor_01HZX9TRJ4M7YQK6P3W2VBDN5M",
                        "prev_cursor": null,
                        "total_count": 247
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              },
              "X-Pagination-Mode": {
                "description": "Pagination mode used for this response (always `cursor` for d.2A operations).",
                "schema": {
                  "type": "string",
                  "enum": [
                    "cursor"
                  ]
                }
              },
              "X-Pagination-Has-More": {
                "description": "Boolean flag (`true`/`false`) indicating whether more pages are available.",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true",
                    "false"
                  ]
                }
              },
              "X-Pagination-Next-Cursor": {
                "description": "Opaque continuation cursor. Omitted when has_more is false.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Pagination-Limit": {
                "description": "Effective per-page limit used for this response.",
                "schema": {
                  "type": "integer",
                  "minimum": 1,
                  "maximum": 100
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "List subaccounts.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/gateway/subaccounts\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/gateway/subaccounts',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/gateway/subaccounts\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/gateway/subaccounts',\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/gateway/subaccounts/{subaccountId}": {
      "get": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "Get subaccount",
        "operationId": "gatewayGetSubaccount",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "subaccountId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Subaccount details",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/StandardResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/GatewaySubaccount"
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Successful response envelope",
                    "value": {
                      "data": {
                        "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                        "merchant_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                        "business_name": "business_name_value",
                        "account_number": "account_number_value",
                        "object": "resource",
                        "created_at": "2026-05-02T10:15:30Z"
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Get subaccount.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/gateway/subaccounts/{subaccountId}\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/gateway/subaccounts/{subaccountId}',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/gateway/subaccounts/{subaccountId}\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/gateway/subaccounts/{subaccountId}',\n]);\n\nprint_r($response->data);"
          }
        ]
      },
      "put": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "Update subaccount",
        "operationId": "gatewayUpdateSubaccount",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "subaccountId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Recommended for safe retries. UUID v4. When supplied, duplicate requests within 24h replay the original response. See Idempotency guide."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "business_name": {
                    "type": "string"
                  },
                  "split_type": {
                    "type": "string"
                  },
                  "split_value": {
                    "type": "number"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Subaccount updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewaySubaccount"
                },
                "examples": {
                  "default": {
                    "summary": "Successful response envelope",
                    "value": {
                      "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                      "merchant_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                      "business_name": "business_name_value",
                      "account_number": "account_number_value",
                      "success": true,
                      "data": {
                        "id": "obj_01HZX9TRJ4M7YQK6P3W2VBDN5K",
                        "object": "resource",
                        "created_at": "2026-05-02T10:15:30Z"
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      }
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Update subaccount.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X PUT \"https://api.kangopenbanking.com/v1/gateway/subaccounts/{subaccountId}\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'PUT',\n  path: '/v1/gateway/subaccounts/{subaccountId}',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"PUT\",\n    path=\"/v1/gateway/subaccounts/{subaccountId}\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'PUT',\n    'path'   => '/v1/gateway/subaccounts/{subaccountId}',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      },
      "delete": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "Delete subaccount",
        "operationId": "gatewayDeleteSubaccount",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "subaccountId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "204": {
            "description": "Subaccount deleted",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            },
            "content": {
              "application/json": {
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Delete subaccount.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X DELETE \"https://api.kangopenbanking.com/v1/gateway/subaccounts/{subaccountId}\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'DELETE',\n  path: '/v1/gateway/subaccounts/{subaccountId}',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"DELETE\",\n    path=\"/v1/gateway/subaccounts/{subaccountId}\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'DELETE',\n    'path'   => '/v1/gateway/subaccounts/{subaccountId}',\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/gateway/customers": {
      "post": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "Create customer",
        "operationId": "gatewayCreateCustomer",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "merchant_id",
                  "email"
                ],
                "properties": {
                  "merchant_id": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "email": {
                    "type": "string"
                  },
                  "phone": {
                    "type": "string"
                  },
                  "name": {
                    "type": "string"
                  },
                  "metadata": {
                    "type": "object"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Customer created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewayCustomer"
                },
                "examples": {
                  "default": {
                    "summary": "Successful response envelope",
                    "value": {
                      "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                      "merchant_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                      "email": "email_value",
                      "success": true,
                      "data": {
                        "id": "obj_01HZX9TRJ4M7YQK6P3W2VBDN5K",
                        "object": "resource",
                        "created_at": "2026-05-02T10:15:30Z"
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      }
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Create customer.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/gateway/customers\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/gateway/customers',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/gateway/customers\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/gateway/customers',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      },
      "get": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "List customers",
        "operationId": "gatewayListCustomers",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "merchant_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Number of items per page. Defaults to 25. Maximum 100. Minimum 1.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 25,
              "example": 25
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "deprecated": true,
            "description": "Deprecated. Retained for legacy initial-page compatibility. Used only when no cursor is supplied. Values greater than zero produce hybrid mode: the first page is offset-based but the response returns a signed continuation cursor for subsequent pages. Once a valid cursor is supplied, offset is ignored. No exact total is calculated. Clients should migrate to cursor.",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          },
          {
            "name": "sort_by",
            "in": "query",
            "required": false,
            "description": "Sort field. Deterministic ordering is `created_at DESC, id DESC`; the UUID `id` is the unique final tie-breaker.",
            "schema": {
              "type": "string",
              "enum": [
                "created_at"
              ],
              "default": "created_at"
            }
          },
          {
            "name": "sort_order",
            "in": "query",
            "required": false,
            "description": "Sort direction. Only descending is supported for cursor pagination.",
            "schema": {
              "type": "string",
              "enum": [
                "desc"
              ],
              "default": "desc"
            }
          },
          {
            "name": "starting_after",
            "in": "query",
            "required": false,
            "deprecated": true,
            "description": "Deprecated cursor alias. Only opaque KOB continuation tokens are recognised; arbitrary database identifiers are not interpreted as cursors. Represents the same forward continuation semantics as `cursor`. Supplying multiple distinct cursor values across `cursor`, `starting_after`, and `ending_before` returns HTTP 400 (`PAGINATION_CURSOR_INVALID`).",
            "schema": {
              "type": "string",
              "maxLength": 512
            }
          },
          {
            "name": "ending_before",
            "in": "query",
            "required": false,
            "deprecated": true,
            "description": "Deprecated cursor alias. Only opaque KOB continuation tokens are recognised; arbitrary database identifiers are not interpreted as cursors. Represents the same forward continuation semantics as `cursor` and does NOT provide backward pagination. Supplying multiple distinct cursor values across `cursor`, `starting_after`, and `ending_before` returns HTTP 400 (`PAGINATION_CURSOR_INVALID`).",
            "schema": {
              "type": "string",
              "maxLength": 512
            }
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          },
          {
            "$ref": "#/components/parameters/CursorParam"
          }
        ],
        "responses": {
          "200": {
            "description": "Customers",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/GatewayCustomer"
                          }
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Cursor-paginated list",
                    "value": {
                      "data": [
                        {
                          "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "merchant_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "email": "email_value",
                          "object": "resource",
                          "created_at": "2026-05-02T10:15:30Z"
                        },
                        {
                          "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "merchant_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "email": "email_value",
                          "object": "resource",
                          "created_at": "2026-05-02T10:15:31Z"
                        }
                      ],
                      "pagination": {
                        "page": 1,
                        "limit": 20,
                        "total": 150,
                        "has_next": true,
                        "has_more": true,
                        "next_cursor": "cursor_01HZX9TRJ4M7YQK6P3W2VBDN5M",
                        "prev_cursor": null,
                        "total_count": 247
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              },
              "X-Pagination-Mode": {
                "description": "Pagination mode used for this response. `cursor` when a signed cursor drove the query; `hybrid` when a legacy `offset` seeded the first page and a signed continuation cursor is returned.",
                "schema": {
                  "type": "string",
                  "enum": [
                    "cursor",
                    "hybrid"
                  ]
                }
              },
              "X-Pagination-Has-More": {
                "description": "Boolean flag indicating whether more pages are available.",
                "schema": {
                  "type": "boolean"
                }
              },
              "X-Pagination-Next-Cursor": {
                "description": "Opaque KOB-signed continuation cursor. An empty header value means no continuation exists.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Pagination-Limit": {
                "description": "Effective per-page limit used for this response.",
                "schema": {
                  "type": "integer",
                  "minimum": 1,
                  "maximum": 100
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "List customers.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.\n\nPagination:\n- Default page size: 25 (`limit`, maximum 100, minimum 1).\n- Cursor is the preferred continuation mechanism. Continuation cursors are opaque KOB-signed tokens with a lifetime of 1800 seconds. Each cursor is bound to the authenticated actor, merchant, environment, and operation; changing a bound filter invalidates the cursor and returns `PAGINATION_CURSOR_FILTER_MISMATCH`.\n- `offset` is deprecated and retained for legacy initial-page compatibility. When `offset > 0` is supplied without a cursor, responses use hybrid mode and return a signed continuation cursor for subsequent pages; once a cursor is present, offset is ignored. No exact total is returned.\n- `starting_after` and `ending_before` are deprecated cursor aliases. Only opaque KOB cursor tokens are accepted. Both represent the same forward continuation semantics; `ending_before` does not provide backward pagination. Supplying multiple distinct cursor values returns HTTP 400.\n- Deterministic ordering: `created_at DESC, id DESC` (the UUID `id` is the final tie-breaker).\n- Successful responses use the `{data, pagination, meta}` envelope. The four response headers `X-Pagination-Mode`, `X-Pagination-Has-More`, `X-Pagination-Next-Cursor`, and `X-Pagination-Limit` mirror the body pagination state.\n\nPagination error codes (HTTP 400 Problem Details): `PAGINATION_LIMIT_INVALID`, `PAGINATION_CURSOR_INVALID`, `PAGINATION_CURSOR_EXPIRED`, `PAGINATION_CURSOR_OPERATION_MISMATCH`, `PAGINATION_CURSOR_SCOPE_MISMATCH`, `PAGINATION_CURSOR_FILTER_MISMATCH`.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/gateway/customers\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/gateway/customers',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/gateway/customers\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/gateway/customers',\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/gateway/customers/{customerId}": {
      "get": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "Get customer",
        "operationId": "gatewayGetCustomer",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "customerId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Customer details",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/StandardResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/GatewayCustomer"
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Successful response envelope",
                    "value": {
                      "data": {
                        "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                        "merchant_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                        "email": "email_value",
                        "object": "resource",
                        "created_at": "2026-05-02T10:15:30Z"
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Get customer.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/gateway/customers/{customerId}\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/gateway/customers/{customerId}',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/gateway/customers/{customerId}\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/gateway/customers/{customerId}',\n]);\n\nprint_r($response->data);"
          }
        ]
      },
      "put": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "Update customer",
        "operationId": "gatewayUpdateCustomer",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "customerId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Recommended for safe retries. UUID v4. When supplied, duplicate requests within 24h replay the original response. See Idempotency guide."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "email": {
                    "type": "string"
                  },
                  "phone": {
                    "type": "string"
                  },
                  "name": {
                    "type": "string"
                  },
                  "metadata": {
                    "type": "object"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Customer updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewayCustomer"
                },
                "examples": {
                  "default": {
                    "summary": "Successful response envelope",
                    "value": {
                      "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                      "merchant_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                      "email": "email_value",
                      "success": true,
                      "data": {
                        "id": "obj_01HZX9TRJ4M7YQK6P3W2VBDN5K",
                        "object": "resource",
                        "created_at": "2026-05-02T10:15:30Z"
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      }
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Update customer.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X PUT \"https://api.kangopenbanking.com/v1/gateway/customers/{customerId}\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'PUT',\n  path: '/v1/gateway/customers/{customerId}',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"PUT\",\n    path=\"/v1/gateway/customers/{customerId}\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'PUT',\n    'path'   => '/v1/gateway/customers/{customerId}',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/gateway/customers/{customerId}/tokens": {
      "get": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "List customer tokens",
        "operationId": "gatewayListCustomerTokens",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "customerId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/LimitParam"
          },
          {
            "$ref": "#/components/parameters/CursorParam"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Customer payment tokens",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/GatewayCustomerToken"
                          }
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Cursor-paginated list",
                    "value": {
                      "data": [
                        {
                          "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "customer_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "channel": "mobile_money",
                          "token_ref": "token_ref_value",
                          "object": "resource",
                          "created_at": "2026-05-02T10:15:30Z"
                        },
                        {
                          "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "customer_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "channel": "mobile_money",
                          "token_ref": "token_ref_value",
                          "object": "resource",
                          "created_at": "2026-05-02T10:15:31Z"
                        }
                      ],
                      "pagination": {
                        "page": 1,
                        "limit": 20,
                        "total": 150,
                        "has_next": true,
                        "has_more": true,
                        "next_cursor": "cursor_01HZX9TRJ4M7YQK6P3W2VBDN5M",
                        "prev_cursor": null,
                        "total_count": 247
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "List customer tokens.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/gateway/customers/{customerId}/tokens\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/gateway/customers/{customerId}/tokens',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/gateway/customers/{customerId}/tokens\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/gateway/customers/{customerId}/tokens',\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/gateway/customers/{customerId}/tokens/{tokenId}": {
      "delete": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "Revoke customer token",
        "operationId": "gatewayRevokeCustomerToken",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "customerId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "tokenId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "204": {
            "description": "Token revoked",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            },
            "content": {
              "application/json": {
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Revoke customer token.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X DELETE \"https://api.kangopenbanking.com/v1/gateway/customers/{customerId}/tokens/{tokenId}\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'DELETE',\n  path: '/v1/gateway/customers/{customerId}/tokens/{tokenId}',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"DELETE\",\n    path=\"/v1/gateway/customers/{customerId}/tokens/{tokenId}\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'DELETE',\n    'path'   => '/v1/gateway/customers/{customerId}/tokens/{tokenId}',\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/gateway/charges/token": {
      "post": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "Charge a saved token",
        "operationId": "gatewayChargeToken",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "token_id",
                  "amount",
                  "tx_ref"
                ],
                "properties": {
                  "token_id": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "amount": {
                    "type": "string",
                    "pattern": "^[0-9]{1,15}$",
                    "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits). Must be consistent with the currency field."
                  },
                  "currency": {
                    "type": "string",
                    "default": "XAF",
                    "enum": [
                      "XAF",
                      "XOF",
                      "USD",
                      "EUR",
                      "GBP",
                      "CNY",
                      "NGN",
                      "GHS",
                      "KES",
                      "ZAR"
                    ],
                    "description": "ISO 4217 currency code. Default is XAF (Central African CFA Franc)."
                  },
                  "tx_ref": {
                    "type": "string"
                  },
                  "metadata": {
                    "type": "object"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Token charge created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewayCharge"
                },
                "examples": {
                  "default": {
                    "summary": "Successful response envelope",
                    "value": {
                      "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                      "merchant_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                      "amount": "5000",
                      "currency": "XAF",
                      "channel": "mobile_money",
                      "status": "pending",
                      "created_at": "2026-05-02T10:15:30Z",
                      "success": true,
                      "data": {
                        "id": "obj_01HZX9TRJ4M7YQK6P3W2VBDN5K",
                        "object": "resource",
                        "created_at": "2026-05-02T10:15:30Z"
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      }
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Charge a saved token.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/gateway/charges/token\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/gateway/charges/token',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/gateway/charges/token\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/gateway/charges/token',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/gateway/charges/{chargeId}/events": {
      "get": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "Get charge events",
        "description": "Get charge events.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "operationId": "gatewayGetChargeEvents",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "chargeId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/LimitParam"
          },
          {
            "$ref": "#/components/parameters/CursorParam"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Charge event timeline",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/GatewayChargeEvent"
                          }
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Cursor-paginated list",
                    "value": {
                      "data": [
                        {
                          "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "charge_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "event_type": "charge.created",
                          "created_at": "2026-05-02T10:15:30Z",
                          "object": "resource"
                        },
                        {
                          "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "charge_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "event_type": "charge.created",
                          "created_at": "2026-05-02T10:15:31Z",
                          "object": "resource"
                        }
                      ],
                      "pagination": {
                        "page": 1,
                        "limit": 20,
                        "total": 150,
                        "has_next": true,
                        "has_more": true,
                        "next_cursor": "cursor_01HZX9TRJ4M7YQK6P3W2VBDN5M",
                        "prev_cursor": null,
                        "total_count": 247
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/gateway/charges/{chargeId}/events\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/gateway/charges/{chargeId}/events',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/gateway/charges/{chargeId}/events\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/gateway/charges/{chargeId}/events',\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/gateway/reconciliation": {
      "post": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "Run reconciliation",
        "operationId": "gatewayRunReconciliation",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "merchant_id",
                  "period_start",
                  "period_end"
                ],
                "properties": {
                  "merchant_id": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "period_start": {
                    "type": "string",
                    "format": "date"
                  },
                  "period_end": {
                    "type": "string",
                    "format": "date"
                  },
                  "provider": {
                    "type": "string",
                    "enum": [
                      "flutterwave",
                      "stripe",
                      "paypal"
                    ],
                    "description": "Payment provider to reconcile against"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Reconciliation started",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewayReconciliationRun"
                },
                "examples": {
                  "default": {
                    "summary": "Successful response envelope",
                    "value": {
                      "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                      "merchant_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                      "status": "pending",
                      "success": true,
                      "data": {
                        "id": "obj_01HZX9TRJ4M7YQK6P3W2VBDN5K",
                        "object": "resource",
                        "created_at": "2026-05-02T10:15:30Z"
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      }
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Run reconciliation.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/gateway/reconciliation\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/gateway/reconciliation',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/gateway/reconciliation\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/gateway/reconciliation',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      },
      "get": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "List reconciliation runs",
        "operationId": "gatewayListReconciliationRuns",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "merchant_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 25,
              "maximum": 100
            },
            "description": "Items per page"
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 0
            },
            "description": "Items to skip"
          },
          {
            "name": "sort_by",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "created_at"
            },
            "description": "Sort field"
          },
          {
            "name": "sort_order",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "asc",
                "desc"
              ],
              "default": "desc"
            },
            "description": "Sort direction"
          },
          {
            "$ref": "#/components/parameters/StartingAfter"
          },
          {
            "$ref": "#/components/parameters/EndingBefore"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Reconciliation runs",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/GatewayReconciliationRun"
                          }
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Successful response envelope",
                    "value": {
                      "data": [
                        {
                          "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "merchant_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "status": "pending"
                        }
                      ],
                      "pagination": {
                        "page": 1,
                        "limit": 20,
                        "total": 150,
                        "has_next": true
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "List reconciliation runs.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/gateway/reconciliation\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/gateway/reconciliation',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/gateway/reconciliation\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/gateway/reconciliation',\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/gateway/reports/fees": {
      "get": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "Fee report",
        "operationId": "gatewayReportFees",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "merchant_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "from",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "to",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "format",
            "in": "query",
            "description": "Response format. Defaults to JSON. Use \"csv\" for spreadsheet export.",
            "schema": {
              "type": "string",
              "enum": [
                "json",
                "csv"
              ],
              "default": "json"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 1000,
              "default": 100
            }
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          },
          {
            "$ref": "#/components/parameters/StartingAfter"
          },
          {
            "$ref": "#/components/parameters/EndingBefore"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Fee report with totals by channel",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "total_fees": {
                      "type": "number",
                      "deprecated": true,
                      "x-successor": "total_fees_money",
                      "x-sunset": "5.0.0",
                      "description": "Deprecated: floating-point monetary value (IEEE-754 binary64 cannot represent decimal minor units exactly). Use `total_fees_money` instead. Removal is scheduled for v5.0.0."
                    },
                    "by_channel": {
                      "type": "object",
                      "additionalProperties": {
                        "type": "number"
                      }
                    },
                    "period": {
                      "type": "string"
                    },
                    "total_fees_money": {
                      "$ref": "#/components/schemas/Money",
                      "description": "Canonical string-encoded successor to `total_fees`. Amount and ISO 4217 currency travel together (ISO 20022 ActiveCurrencyAndAmount). Prefer this field: it is exact for zero-decimal currencies (XAF, XOF) and immune to IEEE-754 drift.",
                      "x-added-in": "4.54.0"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/PaginatedList"
                  }
                }
              },
              "text/csv": {
                "schema": {
                  "type": "string",
                  "format": "binary",
                  "description": "CSV file (RFC 4180). Headers in first row."
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Fee report.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/gateway/reports/fees\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/gateway/reports/fees',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/gateway/reports/fees\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/gateway/reports/fees',\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/gateway/payouts/{payoutId}/retry": {
      "post": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "Retry failed payout",
        "operationId": "gatewayRetryPayout",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "payoutId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Payout retried",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewayPayout"
                },
                "examples": {
                  "default": {
                    "summary": "Successful response envelope",
                    "value": {
                      "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                      "merchant_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                      "amount": "10000",
                      "currency": "XAF",
                      "channel": "mobile_money",
                      "status": "pending",
                      "created_at": "2026-05-02T10:15:30Z",
                      "success": true,
                      "data": {
                        "id": "obj_01HZX9TRJ4M7YQK6P3W2VBDN5K",
                        "object": "resource",
                        "created_at": "2026-05-02T10:15:30Z"
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      }
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Retry failed payout.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/gateway/payouts/{payoutId}/retry\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/gateway/payouts/{payoutId}/retry',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/gateway/payouts/{payoutId}/retry\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/gateway/payouts/{payoutId}/retry',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/merchants": {
      "post": {
        "tags": [
          "Merchant Onboarding"
        ],
        "summary": "Create merchant",
        "operationId": "merchantCreate",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "business_name",
                  "business_type",
                  "contact_email"
                ],
                "properties": {
                  "business_name": {
                    "type": "string"
                  },
                  "business_type": {
                    "type": "string"
                  },
                  "contact_email": {
                    "type": "string"
                  },
                  "contact_phone": {
                    "type": "string"
                  },
                  "country": {
                    "type": "string",
                    "default": "CM"
                  },
                  "action": {
                    "type": "string",
                    "enum": [
                      "create",
                      "submit",
                      "activate",
                      "suspend"
                    ],
                    "default": "create"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Merchant created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewayMerchant"
                },
                "examples": {
                  "default": {
                    "summary": "Successful response envelope",
                    "value": {
                      "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                      "business_name": "business_name_value",
                      "business_type": "business_type_value",
                      "contact_email": "contact_email_value",
                      "success": true,
                      "data": {
                        "id": "obj_01HZX9TRJ4M7YQK6P3W2VBDN5K",
                        "object": "resource",
                        "created_at": "2026-05-02T10:15:30Z"
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      }
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Create merchant.\n\n**Tag:** Merchant Onboarding\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/merchants\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/merchants',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/merchants\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/merchants',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      },
      "get": {
        "tags": [
          "Merchant Onboarding"
        ],
        "summary": "List merchants",
        "operationId": "merchantList",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 25,
              "maximum": 100
            },
            "description": "Items per page"
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 0
            },
            "description": "Items to skip"
          },
          {
            "name": "sort_by",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "created_at"
            },
            "description": "Sort field"
          },
          {
            "name": "sort_order",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "asc",
                "desc"
              ],
              "default": "desc"
            },
            "description": "Sort direction"
          },
          {
            "$ref": "#/components/parameters/StartingAfter"
          },
          {
            "$ref": "#/components/parameters/EndingBefore"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Merchants",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/GatewayMerchant"
                          }
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Cursor-paginated list",
                    "value": {
                      "data": [
                        {
                          "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "business_name": "business_name_value",
                          "business_type": "business_type_value",
                          "contact_email": "contact_email_value",
                          "object": "resource",
                          "created_at": "2026-05-02T10:15:30Z"
                        },
                        {
                          "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "business_name": "business_name_value",
                          "business_type": "business_type_value",
                          "contact_email": "contact_email_value",
                          "object": "resource",
                          "created_at": "2026-05-02T10:15:31Z"
                        }
                      ],
                      "pagination": {
                        "page": 1,
                        "limit": 20,
                        "total": 150,
                        "has_next": true,
                        "has_more": true,
                        "next_cursor": "cursor_01HZX9TRJ4M7YQK6P3W2VBDN5M",
                        "prev_cursor": null,
                        "total_count": 247
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "List merchants.\n\n**Tag:** Merchant Onboarding\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/merchants\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/merchants',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/merchants\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/merchants',\n]);\n\nprint_r($response->data);"
          }
        ]
      },
      "patch": {
        "tags": [
          "Merchant Onboarding"
        ],
        "summary": "Update merchant",
        "operationId": "merchantUpdate",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "merchant_id": {
                    "type": "string"
                  },
                  "business_name": {
                    "type": "string"
                  },
                  "contact_email": {
                    "type": "string"
                  },
                  "logo_url": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Merchant updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewayMerchant"
                },
                "examples": {
                  "default": {
                    "summary": "Successful response envelope",
                    "value": {
                      "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                      "business_name": "business_name_value",
                      "business_type": "business_type_value",
                      "contact_email": "contact_email_value",
                      "success": true,
                      "data": {
                        "id": "obj_01HZX9TRJ4M7YQK6P3W2VBDN5K",
                        "object": "resource",
                        "created_at": "2026-05-02T10:15:30Z"
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      }
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "description": "Update merchant.\n\n**Tag:** Merchant Onboarding\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X PATCH \"https://api.kangopenbanking.com/v1/merchants\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'PATCH',\n  path: '/v1/merchants',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"PATCH\",\n    path=\"/v1/merchants\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'PATCH',\n    'path'   => '/v1/merchants',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/merchants/kyb": {
      "post": {
        "tags": [
          "Merchant Onboarding"
        ],
        "summary": "Submit KYB verification",
        "operationId": "merchantSubmitKyb",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "merchant_id"
                ],
                "properties": {
                  "merchant_id": {
                    "type": "string"
                  },
                  "registration_number": {
                    "type": "string"
                  },
                  "tax_id": {
                    "type": "string"
                  },
                  "documents": {
                    "type": "array",
                    "items": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "KYB submitted",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Submit KYB verification.\n\n**Tag:** Merchant Onboarding\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/merchants/kyb\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/merchants/kyb',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/merchants/kyb\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/merchants/kyb',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      },
      "get": {
        "tags": [
          "Merchant Onboarding"
        ],
        "summary": "Get KYB status",
        "operationId": "merchantGetKyb",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "merchant_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "KYB verification status",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "merchant_id": {
                      "type": "string"
                    },
                    "kyb_status": {
                      "type": "string",
                      "enum": [
                        "not_submitted",
                        "pending",
                        "approved",
                        "rejected"
                      ]
                    },
                    "submitted_at": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "reviewed_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Get KYB status.\n\n**Tag:** Merchant Onboarding\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/merchants/kyb\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/merchants/kyb',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/merchants/kyb\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/merchants/kyb',\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/merchants/api-keys": {
      "post": {
        "tags": [
          "Merchant Onboarding"
        ],
        "summary": "Issue API key",
        "operationId": "merchantIssueApiKey",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "merchant_id"
                ],
                "properties": {
                  "merchant_id": {
                    "type": "string"
                  },
                  "environment": {
                    "type": "string",
                    "enum": [
                      "sandbox",
                      "production"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "API key issued",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "public_key": {
                      "type": "string"
                    },
                    "secret_key": {
                      "type": "string",
                      "description": "Shown only once"
                    },
                    "environment": {
                      "type": "string"
                    },
                    "label": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Issue API key.\n\n**Tag:** Merchant Onboarding\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/merchants/api-keys\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/merchants/api-keys',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/merchants/api-keys\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/merchants/api-keys',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      },
      "get": {
        "tags": [
          "Merchant Onboarding"
        ],
        "summary": "List API keys",
        "operationId": "merchantListApiKeys",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "merchant_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/LimitParam"
          },
          {
            "$ref": "#/components/parameters/CursorParam"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "API keys list",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {}
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Cursor-paginated list",
                    "value": {
                      "data": [
                        "data_value",
                        "data_value"
                      ],
                      "pagination": {
                        "page": 1,
                        "limit": 20,
                        "total": 150,
                        "has_next": true,
                        "has_more": true,
                        "next_cursor": "cursor_01HZX9TRJ4M7YQK6P3W2VBDN5M",
                        "prev_cursor": null,
                        "total_count": 247
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "List API keys.\n\n**Tag:** Merchant Onboarding\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/merchants/api-keys\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/merchants/api-keys',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/merchants/api-keys\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/merchants/api-keys',\n]);\n\nprint_r($response->data);"
          }
        ]
      },
      "delete": {
        "tags": [
          "Merchant Onboarding"
        ],
        "summary": "Revoke API key",
        "operationId": "merchantRevokeApiKey",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "key_id"
                ],
                "properties": {
                  "key_id": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "204": {
            "description": "API key revoked",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            },
            "content": {
              "application/json": {
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "description": "Revoke API key.\n\n**Tag:** Merchant Onboarding\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X DELETE \"https://api.kangopenbanking.com/v1/merchants/api-keys\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'DELETE',\n  path: '/v1/merchants/api-keys',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"DELETE\",\n    path=\"/v1/merchants/api-keys\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'DELETE',\n    'path'   => '/v1/merchants/api-keys',\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/merchants/settlement-accounts": {
      "post": {
        "tags": [
          "Merchant Onboarding"
        ],
        "summary": "Add settlement account",
        "operationId": "merchantAddSettlementAccount",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "merchant_id",
                  "account_number",
                  "bank_code"
                ],
                "properties": {
                  "merchant_id": {
                    "type": "string"
                  },
                  "account_number": {
                    "type": "string"
                  },
                  "bank_code": {
                    "type": "string"
                  },
                  "bank_name": {
                    "type": "string"
                  },
                  "currency": {
                    "type": "string",
                    "default": "XAF",
                    "enum": [
                      "XAF",
                      "XOF",
                      "USD",
                      "EUR",
                      "GBP",
                      "CNY",
                      "NGN",
                      "GHS",
                      "KES",
                      "ZAR"
                    ],
                    "description": "ISO 4217 currency code. Default is XAF (Central African CFA Franc)."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Settlement account added",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Add settlement account.\n\n**Tag:** Merchant Onboarding\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/merchants/settlement-accounts\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/merchants/settlement-accounts',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/merchants/settlement-accounts\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/merchants/settlement-accounts',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      },
      "get": {
        "tags": [
          "Merchant Onboarding"
        ],
        "summary": "List settlement accounts",
        "operationId": "merchantListSettlementAccounts",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "merchant_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/LimitParam"
          },
          {
            "$ref": "#/components/parameters/CursorParam"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Settlement accounts",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {}
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Cursor-paginated list",
                    "value": {
                      "data": [
                        "data_value",
                        "data_value"
                      ],
                      "pagination": {
                        "page": 1,
                        "limit": 20,
                        "total": 150,
                        "has_next": true,
                        "has_more": true,
                        "next_cursor": "cursor_01HZX9TRJ4M7YQK6P3W2VBDN5M",
                        "prev_cursor": null,
                        "total_count": 247
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "List settlement accounts.\n\n**Tag:** Merchant Onboarding\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/merchants/settlement-accounts\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/merchants/settlement-accounts',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/merchants/settlement-accounts\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/merchants/settlement-accounts',\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/merchants/webhooks": {
      "post": {
        "tags": [
          "Merchant Onboarding"
        ],
        "summary": "Register merchant webhook",
        "operationId": "merchantRegisterWebhook",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "merchant_id",
                  "url",
                  "events"
                ],
                "properties": {
                  "merchant_id": {
                    "type": "string"
                  },
                  "url": {
                    "type": "string",
                    "format": "uri"
                  },
                  "events": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Webhook registered",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "url": {
                      "type": "string"
                    },
                    "events": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "secret": {
                      "type": "string",
                      "description": "HMAC secret — shown once"
                    },
                    "status": {
                      "type": "string"
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "**Deprecated.** Use Webhooks v2 (`/v1/webhooks/v2/endpoints`). Sunset: 2026-12-31.\n\nRegister merchant webhook.\n\n**Tag:** Merchant Onboarding\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.\n\n**Migration:** Replace with `webhookV2Create`. Move the endpoint to Webhooks v2 and verify the timestamped `X-Webhook-Signature` described in the webhook definitions.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/merchants/webhooks\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/merchants/webhooks',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/merchants/webhooks\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/merchants/webhooks',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ],
        "deprecated": true,
        "x-sunset-date": "2026-12-31",
        "x-successor": "/v1/webhooks/v2/endpoints",
        "x-replacement-operation-ids": [
          "webhookV2Create"
        ],
        "x-migration-guide": "Move the endpoint to Webhooks v2 and verify the timestamped `X-Webhook-Signature` described in the webhook definitions."
      },
      "get": {
        "tags": [
          "Merchant Onboarding"
        ],
        "summary": "List merchant webhooks",
        "operationId": "merchantListWebhooks",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "merchant_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/LimitParam"
          },
          {
            "$ref": "#/components/parameters/CursorParam"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Merchant webhooks",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/Webhook"
                          }
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Cursor-paginated list",
                    "value": {
                      "data": [
                        {
                          "webhook_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "url": "https://api.kangopenbanking.com/v1/resource/3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "events": [
                            {
                              "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                              "event": "charge.created",
                              "created_at": "2025-03-27T14:32:00Z",
                              "api_version": "4.6.0",
                              "data": {},
                              "type": "type_value",
                              "version": "version_value"
                            }
                          ],
                          "is_active": true
                        }
                      ],
                      "pagination": {
                        "page": 1,
                        "limit": 20,
                        "total": 150,
                        "has_next": true
                      },
                      "meta": {
                        "request_id": "550e8400-e29b-41d4-a716-446655440000",
                        "timestamp": "2025-03-27T12:00:00Z"
                      }
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "**Deprecated.** Use Webhooks v2 (`/v1/webhooks/v2/endpoints`). Sunset: 2026-12-31.\n\nList merchant webhooks.\n\n**Tag:** Merchant Onboarding\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.\n\n**Migration:** Replace with `webhookV2List`. Move the endpoint to Webhooks v2 and verify the timestamped `X-Webhook-Signature` described in the webhook definitions.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/merchants/webhooks\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/merchants/webhooks',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/merchants/webhooks\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/merchants/webhooks',\n]);\n\nprint_r($response->data);"
          }
        ],
        "deprecated": true,
        "x-sunset-date": "2026-12-31",
        "x-successor": "/v1/webhooks/v2/endpoints",
        "x-replacement-operation-ids": [
          "webhookV2List"
        ],
        "x-migration-guide": "Move the endpoint to Webhooks v2 and verify the timestamped `X-Webhook-Signature` described in the webhook definitions."
      }
    },
    "/v1/oauth/revoke": {
      "post": {
        "tags": [
          "OAuth"
        ],
        "summary": "Revoke token",
        "description": "Revoke token.\n\n**Tag:** OAuth\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "operationId": "oauthRevoke",
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "required": [
                  "token",
                  "client_id",
                  "client_secret"
                ],
                "properties": {
                  "token": {
                    "type": "string"
                  },
                  "token_type_hint": {
                    "type": "string",
                    "enum": [
                      "access_token",
                      "refresh_token"
                    ]
                  },
                  "client_id": {
                    "type": "string"
                  },
                  "client_secret": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Token revoked (or was already invalid)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/oauth/revoke\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/oauth/revoke',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/oauth/revoke\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/oauth/revoke',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ]
      }
    },
    "/v1/oauth/userinfo": {
      "get": {
        "tags": [
          "OAuth"
        ],
        "summary": "Get user info",
        "description": "OpenID Connect UserInfo endpoint. Returns claims about the authenticated user based on the access token scope.",
        "operationId": "oauthUserInfo",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "User claims",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "sub": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "email": {
                      "type": "string"
                    },
                    "phone_number": {
                      "type": "string"
                    },
                    "updated_at": {
                      "type": "integer"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request — validation failed or malformed input.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          },
          "401": {
            "description": "Invalid or expired token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          },
          "403": {
            "description": "Token missing openid scope",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          },
          "429": {
            "description": "Too Many Requests — rate limit exceeded.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/oauth/userinfo\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/oauth/userinfo',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/oauth/userinfo\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/oauth/userinfo',\n]);\n\nprint_r($response->data);"
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ]
      }
    },
    "/v1/consumer/piggybank": {
      "post": {
        "tags": [
          "Consumer Tools"
        ],
        "summary": "Create savings goal",
        "description": "Create savings goal.\n\n**Tag:** Consumer Tools\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "operationId": "piggybankCreate",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "name",
                  "target_amount",
                  "currency"
                ],
                "properties": {
                  "name": {
                    "type": "string",
                    "example": "Emergency Fund"
                  },
                  "target_amount": {
                    "type": "number",
                    "example": 500000,
                    "deprecated": true,
                    "x-successor": "target_amount_money",
                    "x-sunset": "5.0.0",
                    "description": "Deprecated: floating-point monetary value (IEEE-754 binary64 cannot represent decimal minor units exactly). Use `target_amount_money` instead. Removal is scheduled for v5.0.0."
                  },
                  "currency": {
                    "type": "string",
                    "default": "XAF",
                    "enum": [
                      "XAF",
                      "XOF",
                      "USD",
                      "EUR",
                      "GBP",
                      "CNY",
                      "NGN",
                      "GHS",
                      "KES",
                      "ZAR"
                    ],
                    "description": "ISO 4217 currency code. Default is XAF (Central African CFA Franc)."
                  },
                  "frequency": {
                    "type": "string",
                    "enum": [
                      "daily",
                      "weekly",
                      "monthly"
                    ]
                  },
                  "contribution_amount": {
                    "type": "number",
                    "example": 10000,
                    "deprecated": true,
                    "x-successor": "contribution_amount_money",
                    "x-sunset": "5.0.0",
                    "description": "Deprecated: floating-point monetary value (IEEE-754 binary64 cannot represent decimal minor units exactly). Use `contribution_amount_money` instead. Removal is scheduled for v5.0.0."
                  },
                  "target_date": {
                    "type": "string",
                    "format": "date"
                  },
                  "target_amount_money": {
                    "$ref": "#/components/schemas/Money",
                    "description": "Canonical string-encoded successor to `target_amount`. Amount and ISO 4217 currency travel together (ISO 20022 ActiveCurrencyAndAmount). Prefer this field: it is exact for zero-decimal currencies (XAF, XOF) and immune to IEEE-754 drift.",
                    "x-added-in": "4.54.0"
                  },
                  "contribution_amount_money": {
                    "$ref": "#/components/schemas/Money",
                    "description": "Canonical string-encoded successor to `contribution_amount`. Amount and ISO 4217 currency travel together (ISO 20022 ActiveCurrencyAndAmount). Prefer this field: it is exact for zero-decimal currencies (XAF, XOF) and immune to IEEE-754 drift.",
                    "x-added-in": "4.54.0"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Piggy bank created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "name": {
                      "type": "string"
                    },
                    "target_amount": {
                      "type": "number",
                      "deprecated": true,
                      "x-successor": "target_amount_money",
                      "x-sunset": "5.0.0",
                      "description": "Deprecated: floating-point monetary value (IEEE-754 binary64 cannot represent decimal minor units exactly). Use `target_amount_money` instead. Removal is scheduled for v5.0.0."
                    },
                    "current_amount": {
                      "type": "number",
                      "example": 0,
                      "deprecated": true,
                      "x-successor": "current_amount_money",
                      "x-sunset": "5.0.0",
                      "description": "Deprecated: floating-point monetary value (IEEE-754 binary64 cannot represent decimal minor units exactly). Use `current_amount_money` instead. Removal is scheduled for v5.0.0."
                    },
                    "currency": {
                      "type": "string",
                      "enum": [
                        "XAF",
                        "XOF",
                        "USD",
                        "EUR",
                        "GBP",
                        "CNY",
                        "NGN",
                        "GHS",
                        "KES",
                        "ZAR"
                      ],
                      "default": "XAF",
                      "description": "ISO 4217 currency code. Default is XAF (Central African CFA Franc)."
                    },
                    "status": {
                      "type": "string",
                      "example": "active"
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "target_amount_money": {
                      "$ref": "#/components/schemas/Money",
                      "description": "Canonical string-encoded successor to `target_amount`. Amount and ISO 4217 currency travel together (ISO 20022 ActiveCurrencyAndAmount). Prefer this field: it is exact for zero-decimal currencies (XAF, XOF) and immune to IEEE-754 drift.",
                      "x-added-in": "4.54.0"
                    },
                    "current_amount_money": {
                      "$ref": "#/components/schemas/Money",
                      "description": "Canonical string-encoded successor to `current_amount`. Amount and ISO 4217 currency travel together (ISO 20022 ActiveCurrencyAndAmount). Prefer this field: it is exact for zero-decimal currencies (XAF, XOF) and immune to IEEE-754 drift.",
                      "x-added-in": "4.54.0"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/consumer/piggybank\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/consumer/piggybank',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/consumer/piggybank\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/consumer/piggybank',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/consumer/piggybank/pay": {
      "post": {
        "tags": [
          "Consumer Tools"
        ],
        "summary": "Make piggy bank payment",
        "description": "Contribute to a savings goal. Impacts credit score positively (+3 to +10 points for on-time payments).",
        "operationId": "piggybankPay",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "piggybank_id",
                  "amount"
                ],
                "properties": {
                  "piggybank_id": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "amount": {
                    "type": "string",
                    "example": "10000",
                    "pattern": "^[0-9]{1,15}$",
                    "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits)."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Payment recorded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/consumer/piggybank/pay\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/consumer/piggybank/pay',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/consumer/piggybank/pay\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/consumer/piggybank/pay',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/consumer/njangi": {
      "post": {
        "tags": [
          "Consumer Tools"
        ],
        "summary": "Create Njangi group",
        "description": "Create a rotating savings circle (Njangi/tontine) with contribution schedule and payout rules.",
        "operationId": "njangiCreate",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "name",
                  "contribution_amount",
                  "frequency"
                ],
                "properties": {
                  "name": {
                    "type": "string",
                    "example": "Office Njangi"
                  },
                  "contribution_amount": {
                    "type": "number",
                    "example": 25000,
                    "deprecated": true,
                    "x-successor": "contribution_amount_money",
                    "x-sunset": "5.0.0",
                    "description": "Deprecated: floating-point monetary value (IEEE-754 binary64 cannot represent decimal minor units exactly). Use `contribution_amount_money` instead. Removal is scheduled for v5.0.0."
                  },
                  "currency": {
                    "type": "string",
                    "default": "XAF",
                    "enum": [
                      "XAF",
                      "XOF",
                      "USD",
                      "EUR",
                      "GBP",
                      "CNY",
                      "NGN",
                      "GHS",
                      "KES",
                      "ZAR"
                    ],
                    "description": "ISO 4217 currency code. Default is XAF (Central African CFA Franc)."
                  },
                  "frequency": {
                    "type": "string",
                    "enum": [
                      "weekly",
                      "monthly"
                    ]
                  },
                  "max_members": {
                    "type": "integer",
                    "example": 10
                  },
                  "payout_method": {
                    "type": "string",
                    "enum": [
                      "random",
                      "sequential",
                      "manual"
                    ],
                    "default": "random"
                  },
                  "contribution_amount_money": {
                    "$ref": "#/components/schemas/Money",
                    "description": "Canonical string-encoded successor to `contribution_amount`. Amount and ISO 4217 currency travel together (ISO 20022 ActiveCurrencyAndAmount). Prefer this field: it is exact for zero-decimal currencies (XAF, XOF) and immune to IEEE-754 drift.",
                    "x-added-in": "4.54.0"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Njangi group created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "name": {
                      "type": "string"
                    },
                    "contribution_amount": {
                      "type": "number",
                      "deprecated": true,
                      "x-successor": "contribution_amount_money",
                      "x-sunset": "5.0.0",
                      "description": "Deprecated: floating-point monetary value (IEEE-754 binary64 cannot represent decimal minor units exactly). Use `contribution_amount_money` instead. Removal is scheduled for v5.0.0."
                    },
                    "currency": {
                      "type": "string",
                      "enum": [
                        "XAF",
                        "XOF",
                        "USD",
                        "EUR",
                        "GBP",
                        "CNY",
                        "NGN",
                        "GHS",
                        "KES",
                        "ZAR"
                      ],
                      "default": "XAF",
                      "description": "ISO 4217 currency code. Default is XAF (Central African CFA Franc)."
                    },
                    "frequency": {
                      "type": "string"
                    },
                    "member_count": {
                      "type": "integer",
                      "example": 1
                    },
                    "status": {
                      "type": "string",
                      "example": "active"
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "contribution_amount_money": {
                      "$ref": "#/components/schemas/Money",
                      "description": "Canonical string-encoded successor to `contribution_amount`. Amount and ISO 4217 currency travel together (ISO 20022 ActiveCurrencyAndAmount). Prefer this field: it is exact for zero-decimal currencies (XAF, XOF) and immune to IEEE-754 drift.",
                      "x-added-in": "4.54.0"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/consumer/njangi\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/consumer/njangi',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/consumer/njangi\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/consumer/njangi',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/consumer/njangi/join": {
      "post": {
        "tags": [
          "Consumer Tools"
        ],
        "summary": "Join Njangi group",
        "operationId": "njangiJoin",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "group_id"
                ],
                "properties": {
                  "group_id": {
                    "type": "string",
                    "format": "uuid"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Joined group",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Recommended for safe retries. UUID v4. When supplied, duplicate requests within 24h replay the original response. See Idempotency guide."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "description": "Join Njangi group.\n\n**Tag:** Consumer Tools\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/consumer/njangi/join\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/consumer/njangi/join',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/consumer/njangi/join\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/consumer/njangi/join',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/consumer/njangi/contribute": {
      "post": {
        "tags": [
          "Consumer Tools"
        ],
        "summary": "Make Njangi contribution",
        "description": "Submit a contribution to the group pot. Late contributions are reported as negative credit events.",
        "operationId": "njangiContribute",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "group_id",
                  "amount"
                ],
                "properties": {
                  "group_id": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "amount": {
                    "type": "string",
                    "example": "25000",
                    "pattern": "^[0-9]{1,15}$",
                    "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits)."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Contribution recorded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/consumer/njangi/contribute\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/consumer/njangi/contribute',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/consumer/njangi/contribute\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/consumer/njangi/contribute',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/consumer/njangi/payout": {
      "post": {
        "tags": [
          "Consumer Tools"
        ],
        "summary": "Trigger Njangi payout",
        "description": "Trigger Njangi payout.\n\n**Tag:** Consumer Tools\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "operationId": "njangiPayout",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "group_id"
                ],
                "properties": {
                  "group_id": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "recipient_id": {
                    "type": "string",
                    "format": "uuid",
                    "description": "Override random selection (manual mode only)"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Payout initiated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/consumer/njangi/payout\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/consumer/njangi/payout',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/consumer/njangi/payout\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/consumer/njangi/payout',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/gateway/funding-intents": {
      "post": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "Create funding intent",
        "description": "Create an intent to fund a merchant or user account. Supports Stripe, PayPal, and mobile money sources.",
        "operationId": "gatewayCreateFundingIntent",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "amount",
                  "currency",
                  "source"
                ],
                "properties": {
                  "amount": {
                    "type": "string",
                    "example": "50000",
                    "pattern": "^[0-9]{1,15}$",
                    "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits). Must be consistent with the currency field."
                  },
                  "currency": {
                    "type": "string",
                    "default": "XAF",
                    "enum": [
                      "XAF",
                      "XOF",
                      "USD",
                      "EUR",
                      "GBP",
                      "CNY",
                      "NGN",
                      "GHS",
                      "KES",
                      "ZAR"
                    ],
                    "description": "ISO 4217 currency code. Default is XAF (Central African CFA Franc)."
                  },
                  "source": {
                    "type": "string",
                    "enum": [
                      "stripe",
                      "paypal",
                      "mobile_money"
                    ]
                  },
                  "metadata": {
                    "type": "object"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Funding intent created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "amount": {
                      "type": "string",
                      "pattern": "^[0-9]{1,15}$",
                      "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits). Must be consistent with the currency field."
                    },
                    "currency": {
                      "type": "string",
                      "enum": [
                        "XAF",
                        "XOF",
                        "USD",
                        "EUR",
                        "GBP",
                        "CNY",
                        "NGN",
                        "GHS",
                        "KES",
                        "ZAR"
                      ],
                      "default": "XAF",
                      "description": "ISO 4217 currency code. Default is XAF (Central African CFA Franc)."
                    },
                    "source": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "pending",
                        "confirmed",
                        "cancelled",
                        "failed"
                      ]
                    },
                    "redirect_url": {
                      "type": "string"
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/gateway/funding-intents\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/gateway/funding-intents',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/gateway/funding-intents\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/gateway/funding-intents',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      },
      "get": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "List funding intents",
        "operationId": "gatewayListFundingIntents",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 25,
              "maximum": 100
            },
            "description": "Items per page"
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 0
            },
            "description": "Items to skip"
          },
          {
            "name": "sort_by",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "created_at"
            },
            "description": "Sort field"
          },
          {
            "name": "sort_order",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "asc",
                "desc"
              ],
              "default": "desc"
            },
            "description": "Sort direction"
          },
          {
            "$ref": "#/components/parameters/StartingAfter"
          },
          {
            "$ref": "#/components/parameters/EndingBefore"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Funding intents list",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {}
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Cursor-paginated list",
                    "value": {
                      "data": [
                        "data_value",
                        "data_value"
                      ],
                      "pagination": {
                        "page": 1,
                        "limit": 20,
                        "total": 150,
                        "has_next": true,
                        "has_more": true,
                        "next_cursor": "cursor_01HZX9TRJ4M7YQK6P3W2VBDN5M",
                        "prev_cursor": null,
                        "total_count": 247
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "List funding intents.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/gateway/funding-intents\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/gateway/funding-intents',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/gateway/funding-intents\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/gateway/funding-intents',\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/gateway/funding-intents/{intentId}": {
      "get": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "Get funding intent",
        "operationId": "gatewayGetFundingIntent",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "intentId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Funding intent details",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "amount": {
                      "type": "string",
                      "pattern": "^[0-9]{1,15}$",
                      "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits). Must be consistent with the currency field."
                    },
                    "currency": {
                      "type": "string",
                      "enum": [
                        "XAF",
                        "XOF",
                        "USD",
                        "EUR",
                        "GBP",
                        "CNY",
                        "NGN",
                        "GHS",
                        "KES",
                        "ZAR"
                      ],
                      "default": "XAF",
                      "description": "ISO 4217 currency code. Default is XAF (Central African CFA Franc)."
                    },
                    "source": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string"
                    },
                    "redirect_url": {
                      "type": "string"
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Get funding intent.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/gateway/funding-intents/{intentId}\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/gateway/funding-intents/{intentId}',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/gateway/funding-intents/{intentId}\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/gateway/funding-intents/{intentId}',\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/gateway/funding-intents/{intentId}/cancel": {
      "post": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "Cancel funding intent",
        "operationId": "gatewayCancelFundingIntent",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "intentId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Funding intent cancelled",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Cancel funding intent.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/gateway/funding-intents/{intentId}/cancel\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/gateway/funding-intents/{intentId}/cancel',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/gateway/funding-intents/{intentId}/cancel\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/gateway/funding-intents/{intentId}/cancel',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/gateway/funding-intents/{intentId}/confirm": {
      "post": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "Confirm funding intent",
        "description": "Confirm funding intent.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "operationId": "gatewayConfirmFundingIntent",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "intentId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Funding confirmed and account credited",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/gateway/funding-intents/{intentId}/confirm\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/gateway/funding-intents/{intentId}/confirm',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/gateway/funding-intents/{intentId}/confirm\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/gateway/funding-intents/{intentId}/confirm',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/teller/transaction": {
      "post": {
        "tags": [
          "Banking Operations"
        ],
        "summary": "Teller transaction",
        "description": "Teller transaction.\n\n**Tag:** Banking Operations\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "operationId": "tellerTransaction",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "account_id",
                  "amount",
                  "transaction_type"
                ],
                "properties": {
                  "account_id": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "amount": {
                    "type": "string",
                    "example": "100000",
                    "pattern": "^[0-9]{1,15}$",
                    "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits). Must be consistent with the currency field."
                  },
                  "currency": {
                    "type": "string",
                    "default": "XAF",
                    "enum": [
                      "XAF",
                      "XOF",
                      "USD",
                      "EUR",
                      "GBP",
                      "CNY",
                      "NGN",
                      "GHS",
                      "KES",
                      "ZAR"
                    ],
                    "description": "ISO 4217 currency code. Default is XAF (Central African CFA Franc)."
                  },
                  "transaction_type": {
                    "type": "string",
                    "enum": [
                      "deposit",
                      "withdrawal"
                    ]
                  },
                  "narration": {
                    "type": "string"
                  },
                  "branch_id": {
                    "type": "string",
                    "format": "uuid"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Transaction processed",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "transaction_id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "status": {
                      "type": "string"
                    },
                    "amount": {
                      "type": "string",
                      "pattern": "^[0-9]{1,15}$",
                      "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits)."
                    },
                    "balance_after": {
                      "type": "number",
                      "deprecated": true,
                      "x-successor": "balance_after_money",
                      "x-sunset": "5.0.0",
                      "description": "Deprecated: floating-point monetary value (IEEE-754 binary64 cannot represent decimal minor units exactly). Use `balance_after_money` instead. Removal is scheduled for v5.0.0."
                    },
                    "balance_after_money": {
                      "$ref": "#/components/schemas/Money",
                      "description": "Canonical string-encoded successor to `balance_after`. Amount and ISO 4217 currency travel together (ISO 20022 ActiveCurrencyAndAmount). Prefer this field: it is exact for zero-decimal currencies (XAF, XOF) and immune to IEEE-754 drift.",
                      "x-added-in": "4.54.0"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/teller/transaction\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/teller/transaction',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/teller/transaction\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/teller/transaction',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/admin/withdrawal-policies": {
      "get": {
        "tags": [
          "Operational Controls"
        ],
        "summary": "List withdrawal policies",
        "operationId": "listWithdrawalPolicies",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "institution_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "$ref": "#/components/parameters/LimitParam"
          },
          {
            "$ref": "#/components/parameters/CursorParam"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Withdrawal policies list",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {}
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Cursor-paginated list",
                    "value": {
                      "data": [
                        "data_value",
                        "data_value"
                      ],
                      "pagination": {
                        "page": 1,
                        "limit": 20,
                        "total": 150,
                        "has_next": true,
                        "has_more": true,
                        "next_cursor": "cursor_01HZX9TRJ4M7YQK6P3W2VBDN5M",
                        "prev_cursor": null,
                        "total_count": 247
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "List withdrawal policies.\n\n**Tag:** Operational Controls\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/admin/withdrawal-policies\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/admin/withdrawal-policies',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/admin/withdrawal-policies\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/admin/withdrawal-policies',\n]);\n\nprint_r($response->data);"
          }
        ]
      },
      "post": {
        "tags": [
          "Operational Controls"
        ],
        "summary": "Create withdrawal policy",
        "operationId": "createWithdrawalPolicy",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "institution_id",
                  "role_type",
                  "single_txn_limit",
                  "daily_total_limit"
                ],
                "properties": {
                  "institution_id": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "branch_id": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "currency": {
                    "type": "string",
                    "default": "XAF",
                    "enum": [
                      "XAF",
                      "XOF",
                      "USD",
                      "EUR",
                      "GBP",
                      "CNY",
                      "NGN",
                      "GHS",
                      "KES",
                      "ZAR"
                    ],
                    "description": "ISO 4217 currency code. Default is XAF (Central African CFA Franc)."
                  },
                  "channel": {
                    "type": "string"
                  },
                  "role_type": {
                    "type": "string",
                    "enum": [
                      "teller",
                      "assistant_manager",
                      "branch_manager",
                      "general_manager"
                    ]
                  },
                  "single_txn_limit": {
                    "type": "number",
                    "example": 500000
                  },
                  "daily_total_limit": {
                    "type": "number",
                    "example": 5000000,
                    "deprecated": true,
                    "x-successor": "daily_total_limit_money",
                    "x-sunset": "5.0.0",
                    "description": "Deprecated: floating-point monetary value (IEEE-754 binary64 cannot represent decimal minor units exactly). Use `daily_total_limit_money` instead. Removal is scheduled for v5.0.0."
                  },
                  "auto_approve_threshold": {
                    "type": "number",
                    "example": 100000
                  },
                  "requires_dual_approval_above": {
                    "type": "number"
                  },
                  "escalation_target_role": {
                    "type": "string",
                    "enum": [
                      "assistant_manager",
                      "branch_manager",
                      "general_manager"
                    ]
                  },
                  "can_override_lower_role": {
                    "type": "boolean"
                  },
                  "effective_from": {
                    "type": "string",
                    "format": "date"
                  },
                  "effective_to": {
                    "type": "string",
                    "format": "date"
                  },
                  "daily_total_limit_money": {
                    "$ref": "#/components/schemas/Money",
                    "description": "Canonical string-encoded successor to `daily_total_limit`. Amount and ISO 4217 currency travel together (ISO 20022 ActiveCurrencyAndAmount). Prefer this field: it is exact for zero-decimal currencies (XAF, XOF) and immune to IEEE-754 drift.",
                    "x-added-in": "4.54.0"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Policy created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Create withdrawal policy.\n\n**Tag:** Operational Controls\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/admin/withdrawal-policies\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/admin/withdrawal-policies',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/admin/withdrawal-policies\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/admin/withdrawal-policies',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/admin/withdrawal-policies/{policyId}": {
      "get": {
        "tags": [
          "Operational Controls"
        ],
        "summary": "Get withdrawal policy",
        "operationId": "getWithdrawalPolicy",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "policyId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Policy details",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "role_type": {
                      "type": "string"
                    },
                    "single_txn_limit": {
                      "type": "number"
                    },
                    "daily_total_limit": {
                      "type": "number",
                      "deprecated": true,
                      "x-successor": "daily_total_limit_money",
                      "x-sunset": "5.0.0",
                      "description": "Deprecated: floating-point monetary value (IEEE-754 binary64 cannot represent decimal minor units exactly). Use `daily_total_limit_money` instead. Removal is scheduled for v5.0.0."
                    },
                    "auto_approve_threshold": {
                      "type": "number"
                    },
                    "status": {
                      "type": "string"
                    },
                    "daily_total_limit_money": {
                      "$ref": "#/components/schemas/Money",
                      "description": "Canonical string-encoded successor to `daily_total_limit`. Amount and ISO 4217 currency travel together (ISO 20022 ActiveCurrencyAndAmount). Prefer this field: it is exact for zero-decimal currencies (XAF, XOF) and immune to IEEE-754 drift.",
                      "x-added-in": "4.54.0"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Get withdrawal policy.\n\n**Tag:** Operational Controls\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/admin/withdrawal-policies/{policyId}\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/admin/withdrawal-policies/{policyId}',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/admin/withdrawal-policies/{policyId}\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/admin/withdrawal-policies/{policyId}',\n]);\n\nprint_r($response->data);"
          }
        ]
      },
      "patch": {
        "tags": [
          "Operational Controls"
        ],
        "summary": "Update withdrawal policy",
        "operationId": "updateWithdrawalPolicy",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "policyId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "single_txn_limit": {
                    "type": "number"
                  },
                  "daily_total_limit": {
                    "type": "number",
                    "deprecated": true,
                    "x-successor": "daily_total_limit_money",
                    "x-sunset": "5.0.0",
                    "description": "Deprecated: floating-point monetary value (IEEE-754 binary64 cannot represent decimal minor units exactly). Use `daily_total_limit_money` instead. Removal is scheduled for v5.0.0."
                  },
                  "status": {
                    "type": "string"
                  },
                  "effective_to": {
                    "type": "string",
                    "format": "date"
                  },
                  "daily_total_limit_money": {
                    "$ref": "#/components/schemas/Money",
                    "description": "Canonical string-encoded successor to `daily_total_limit`. Amount and ISO 4217 currency travel together (ISO 20022 ActiveCurrencyAndAmount). Prefer this field: it is exact for zero-decimal currencies (XAF, XOF) and immune to IEEE-754 drift.",
                    "x-added-in": "4.54.0"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Policy updated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Update withdrawal policy.\n\n**Tag:** Operational Controls\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X PATCH \"https://api.kangopenbanking.com/v1/admin/withdrawal-policies/{policyId}\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'PATCH',\n  path: '/v1/admin/withdrawal-policies/{policyId}',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"PATCH\",\n    path=\"/v1/admin/withdrawal-policies/{policyId}\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'PATCH',\n    'path'   => '/v1/admin/withdrawal-policies/{policyId}',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/admin/staff/authorizations": {
      "get": {
        "tags": [
          "Operational Controls"
        ],
        "summary": "List staff authorizations",
        "operationId": "listStaffAuthorizations",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "institution_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "$ref": "#/components/parameters/LimitParam"
          },
          {
            "$ref": "#/components/parameters/CursorParam"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Staff authorizations",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {}
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Cursor-paginated list",
                    "value": {
                      "data": [
                        "data_value",
                        "data_value"
                      ],
                      "pagination": {
                        "page": 1,
                        "limit": 20,
                        "total": 150,
                        "has_next": true,
                        "has_more": true,
                        "next_cursor": "cursor_01HZX9TRJ4M7YQK6P3W2VBDN5M",
                        "prev_cursor": null,
                        "total_count": 247
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "List staff authorizations.\n\n**Tag:** Operational Controls\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/admin/staff/authorizations\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/admin/staff/authorizations',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/admin/staff/authorizations\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/admin/staff/authorizations',\n]);\n\nprint_r($response->data);"
          }
        ]
      },
      "post": {
        "tags": [
          "Operational Controls"
        ],
        "summary": "Create staff authorization",
        "operationId": "createStaffAuthorization",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "institution_id",
                  "user_id",
                  "role_type"
                ],
                "properties": {
                  "institution_id": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "branch_id": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "user_id": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "role_type": {
                    "type": "string",
                    "enum": [
                      "teller",
                      "assistant_manager",
                      "branch_manager",
                      "general_manager"
                    ]
                  },
                  "max_override_limit": {
                    "type": "number"
                  },
                  "can_approve_overdraft": {
                    "type": "boolean"
                  },
                  "can_approve_withdrawal_override": {
                    "type": "boolean"
                  },
                  "can_suspend_overdraft": {
                    "type": "boolean"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Authorization created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Create staff authorization.\n\n**Tag:** Operational Controls\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/admin/staff/authorizations\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/admin/staff/authorizations',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/admin/staff/authorizations\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/admin/staff/authorizations',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/admin/staff/authorizations/{authorizationId}": {
      "get": {
        "tags": [
          "Operational Controls"
        ],
        "summary": "Get staff authorization",
        "operationId": "getStaffAuthorization",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "authorizationId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Authorization details",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "user_id": {
                      "type": "string"
                    },
                    "role_type": {
                      "type": "string"
                    },
                    "max_override_limit": {
                      "type": "number"
                    },
                    "status": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Get staff authorization.\n\n**Tag:** Operational Controls\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/admin/staff/authorizations/{authorizationId}\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/admin/staff/authorizations/{authorizationId}',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/admin/staff/authorizations/{authorizationId}\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/admin/staff/authorizations/{authorizationId}',\n]);\n\nprint_r($response->data);"
          }
        ]
      },
      "patch": {
        "tags": [
          "Operational Controls"
        ],
        "summary": "Update staff authorization",
        "operationId": "updateStaffAuthorization",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "authorizationId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "max_override_limit": {
                    "type": "number"
                  },
                  "can_approve_overdraft": {
                    "type": "boolean"
                  },
                  "can_approve_withdrawal_override": {
                    "type": "boolean"
                  },
                  "status": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Authorization updated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Update staff authorization.\n\n**Tag:** Operational Controls\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X PATCH \"https://api.kangopenbanking.com/v1/admin/staff/authorizations/{authorizationId}\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'PATCH',\n  path: '/v1/admin/staff/authorizations/{authorizationId}',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"PATCH\",\n    path=\"/v1/admin/staff/authorizations/{authorizationId}\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'PATCH',\n    'path'   => '/v1/admin/staff/authorizations/{authorizationId}',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/banking/withdrawal-requests": {
      "post": {
        "tags": [
          "Approval Workflows"
        ],
        "summary": "Create withdrawal request",
        "description": "Create a withdrawal request. If the amount exceeds the staff member's policy limit, the request is automatically routed into the approval workflow.",
        "operationId": "createWithdrawalRequest",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "institution_id",
                  "account_id",
                  "amount"
                ],
                "properties": {
                  "institution_id": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "branch_id": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "account_id": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "amount": {
                    "type": "string",
                    "example": "2000000",
                    "pattern": "^[0-9]{1,15}$",
                    "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits). Must be consistent with the currency field."
                  },
                  "currency": {
                    "type": "string",
                    "default": "XAF",
                    "enum": [
                      "XAF",
                      "XOF",
                      "USD",
                      "EUR",
                      "GBP",
                      "CNY",
                      "NGN",
                      "GHS",
                      "KES",
                      "ZAR"
                    ],
                    "description": "ISO 4217 currency code. Default is XAF (Central African CFA Franc)."
                  },
                  "channel": {
                    "type": "string",
                    "default": "branch"
                  },
                  "reason": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Request auto-approved and executed",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "status": {
                      "type": "string",
                      "example": "approved"
                    },
                    "amount": {
                      "type": "string",
                      "example": "500000",
                      "pattern": "^[0-9]{1,15}$",
                      "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits). Must be consistent with the currency field."
                    },
                    "currency": {
                      "type": "string",
                      "example": "XAF",
                      "enum": [
                        "XAF",
                        "XOF",
                        "USD",
                        "EUR",
                        "GBP",
                        "CNY",
                        "NGN",
                        "GHS",
                        "KES",
                        "ZAR"
                      ],
                      "default": "XAF",
                      "description": "ISO 4217 currency code. Default is XAF (Central African CFA Franc)."
                    },
                    "account_id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "approved_at": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "requires_approval": {
                      "type": "boolean",
                      "example": false
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "202": {
            "description": "Request requires manager approval",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "requires_approval": {
                      "type": "boolean",
                      "example": true
                    },
                    "withdrawal_request_id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "approval_status": {
                      "type": "string"
                    },
                    "pending_role": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/banking/withdrawal-requests\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/banking/withdrawal-requests',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/banking/withdrawal-requests\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/banking/withdrawal-requests',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      },
      "get": {
        "tags": [
          "Approval Workflows"
        ],
        "summary": "List withdrawal requests",
        "operationId": "listWithdrawalRequests",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "institution_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 25,
              "maximum": 100
            },
            "description": "Items per page"
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 0
            },
            "description": "Items to skip"
          },
          {
            "name": "sort_by",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "created_at"
            },
            "description": "Sort field"
          },
          {
            "name": "sort_order",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "asc",
                "desc"
              ],
              "default": "desc"
            },
            "description": "Sort direction"
          },
          {
            "$ref": "#/components/parameters/StartingAfter"
          },
          {
            "$ref": "#/components/parameters/EndingBefore"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Withdrawal requests",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {}
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Cursor-paginated list",
                    "value": {
                      "data": [
                        "data_value",
                        "data_value"
                      ],
                      "pagination": {
                        "page": 1,
                        "limit": 20,
                        "total": 150,
                        "has_next": true,
                        "has_more": true,
                        "next_cursor": "cursor_01HZX9TRJ4M7YQK6P3W2VBDN5M",
                        "prev_cursor": null,
                        "total_count": 247
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "List withdrawal requests.\n\n**Tag:** Approval Workflows\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/banking/withdrawal-requests\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/banking/withdrawal-requests',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/banking/withdrawal-requests\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/banking/withdrawal-requests',\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/banking/withdrawal-requests/{requestId}": {
      "get": {
        "tags": [
          "Approval Workflows"
        ],
        "summary": "Get withdrawal request",
        "operationId": "getWithdrawalRequest",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "requestId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Withdrawal request details",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "account_id": {
                      "type": "string"
                    },
                    "amount": {
                      "type": "string",
                      "pattern": "^[0-9]{1,15}$",
                      "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits). Must be consistent with the currency field."
                    },
                    "currency": {
                      "type": "string",
                      "enum": [
                        "XAF",
                        "XOF",
                        "USD",
                        "EUR",
                        "GBP",
                        "CNY",
                        "NGN",
                        "GHS",
                        "KES",
                        "ZAR"
                      ],
                      "default": "XAF",
                      "description": "ISO 4217 currency code. Default is XAF (Central African CFA Franc)."
                    },
                    "status": {
                      "type": "string"
                    },
                    "approval_id": {
                      "type": "string"
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Get withdrawal request.\n\n**Tag:** Approval Workflows\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/banking/withdrawal-requests/{requestId}\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/banking/withdrawal-requests/{requestId}',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/banking/withdrawal-requests/{requestId}\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/banking/withdrawal-requests/{requestId}',\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/banking/withdrawal-requests/{requestId}/submit": {
      "post": {
        "tags": [
          "Approval Workflows"
        ],
        "summary": "Submit draft withdrawal request",
        "operationId": "submitWithdrawalRequest",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "requestId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Request submitted",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Submit draft withdrawal request.\n\n**Tag:** Approval Workflows\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/banking/withdrawal-requests/{requestId}/submit\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/banking/withdrawal-requests/{requestId}/submit',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/banking/withdrawal-requests/{requestId}/submit\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/banking/withdrawal-requests/{requestId}/submit',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/banking/withdrawal-requests/{requestId}/cancel": {
      "post": {
        "tags": [
          "Approval Workflows"
        ],
        "summary": "Cancel withdrawal request",
        "operationId": "cancelWithdrawalRequest",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "requestId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "reason": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Request cancelled",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Cancel withdrawal request.\n\n**Tag:** Approval Workflows\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/banking/withdrawal-requests/{requestId}/cancel\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/banking/withdrawal-requests/{requestId}/cancel',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/banking/withdrawal-requests/{requestId}/cancel\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/banking/withdrawal-requests/{requestId}/cancel',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/banking/approvals": {
      "get": {
        "tags": [
          "Approval Workflows"
        ],
        "summary": "List approval requests",
        "operationId": "listApprovals",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "institution_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 25,
              "maximum": 100
            },
            "description": "Items per page"
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 0
            },
            "description": "Items to skip"
          },
          {
            "name": "sort_by",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "created_at"
            },
            "description": "Sort field"
          },
          {
            "name": "sort_order",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "asc",
                "desc"
              ],
              "default": "desc"
            },
            "description": "Sort direction"
          },
          {
            "$ref": "#/components/parameters/StartingAfter"
          },
          {
            "$ref": "#/components/parameters/EndingBefore"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Approval requests with action history",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {}
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Cursor-paginated list",
                    "value": {
                      "data": [
                        "data_value",
                        "data_value"
                      ],
                      "pagination": {
                        "page": 1,
                        "limit": 20,
                        "total": 150,
                        "has_next": true,
                        "has_more": true,
                        "next_cursor": "cursor_01HZX9TRJ4M7YQK6P3W2VBDN5M",
                        "prev_cursor": null,
                        "total_count": 247
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "List approval requests.\n\n**Tag:** Approval Workflows\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/banking/approvals\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/banking/approvals',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/banking/approvals\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/banking/approvals',\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/banking/approvals/{approvalId}": {
      "get": {
        "tags": [
          "Approval Workflows"
        ],
        "summary": "Get approval request",
        "operationId": "getApproval",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "approvalId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Approval with full action audit trail",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "entity_type": {
                      "type": "string"
                    },
                    "entity_id": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string"
                    },
                    "actions": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "action": {
                            "type": "string"
                          },
                          "acted_by": {
                            "type": "string"
                          },
                          "comments": {
                            "type": "string"
                          },
                          "created_at": {
                            "type": "string",
                            "format": "date-time"
                          }
                        }
                      }
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Get approval request.\n\n**Tag:** Approval Workflows\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/banking/approvals/{approvalId}\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/banking/approvals/{approvalId}',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/banking/approvals/{approvalId}\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/banking/approvals/{approvalId}',\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/banking/approvals/{approvalId}/approve": {
      "post": {
        "tags": [
          "Approval Workflows"
        ],
        "summary": "Approve request",
        "description": "Approve a pending request. The approver must have the required operational role. If the entity is a withdrawal, it is automatically executed after approval.",
        "operationId": "approveRequest",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "approvalId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "comments": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Approved (and executed if withdrawal)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/banking/approvals/{approvalId}/approve\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/banking/approvals/{approvalId}/approve',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/banking/approvals/{approvalId}/approve\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/banking/approvals/{approvalId}/approve',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/banking/approvals/{approvalId}/reject": {
      "post": {
        "tags": [
          "Approval Workflows"
        ],
        "summary": "Reject request",
        "operationId": "rejectRequest",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "approvalId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "reason"
                ],
                "properties": {
                  "reason": {
                    "type": "string"
                  },
                  "comments": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Rejected",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Reject request.\n\n**Tag:** Approval Workflows\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/banking/approvals/{approvalId}/reject\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/banking/approvals/{approvalId}/reject',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/banking/approvals/{approvalId}/reject\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/banking/approvals/{approvalId}/reject',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/banking/approvals/{approvalId}/escalate": {
      "post": {
        "tags": [
          "Approval Workflows"
        ],
        "summary": "Escalate to higher authority",
        "operationId": "escalateRequest",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "approvalId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "target_role": {
                    "type": "string",
                    "enum": [
                      "branch_manager",
                      "general_manager"
                    ]
                  },
                  "comments": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Escalated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Escalate to higher authority.\n\n**Tag:** Approval Workflows\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/banking/approvals/{approvalId}/escalate\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/banking/approvals/{approvalId}/escalate',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/banking/approvals/{approvalId}/escalate\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/banking/approvals/{approvalId}/escalate',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/accounts/{accountId}/overdraft": {
      "get": {
        "tags": [
          "Overdraft"
        ],
        "summary": "Get overdraft profile",
        "description": "Returns overdraft eligibility, approved limit, utilised and available amounts, risk band, and score factors.",
        "operationId": "getOverdraftProfile",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "accountId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Overdraft profile with score factors",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "eligible": {
                      "type": "boolean"
                    },
                    "recommended_limit": {
                      "type": "string",
                      "example": "250000",
                      "pattern": "^[0-9]{1,15}$",
                      "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits)."
                    },
                    "approved_limit": {
                      "type": "string",
                      "example": "200000",
                      "pattern": "^[0-9]{1,15}$",
                      "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits)."
                    },
                    "utilised_amount": {
                      "type": "string",
                      "example": "50000",
                      "pattern": "^[0-9]{1,15}$",
                      "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits)."
                    },
                    "available_amount": {
                      "type": "string",
                      "example": "150000",
                      "pattern": "^[0-9]{1,15}$",
                      "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits)."
                    },
                    "risk_band": {
                      "type": "string",
                      "enum": [
                        "A",
                        "B",
                        "C",
                        "D",
                        "F"
                      ]
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "active",
                        "suspended",
                        "revoked",
                        "pending_approval",
                        "inactive"
                      ]
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/accounts/{accountId}/overdraft\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/accounts/{accountId}/overdraft',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/accounts/{accountId}/overdraft\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/accounts/{accountId}/overdraft',\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/accounts/{accountId}/overdraft/recalculate": {
      "post": {
        "tags": [
          "Overdraft"
        ],
        "summary": "Recalculate overdraft eligibility",
        "description": "Re-evaluates account behavior (salary consistency, savings, balance, tenure, activity, repayment history, credit score) and produces an explainable overdraft recommendation.",
        "operationId": "recalculateOverdraft",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "accountId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Recommended for safe retries. UUID v4. When supplied, duplicate requests within 24h replay the original response. See Idempotency guide."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Recalculated overdraft profile with score factor breakdown",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "eligible": {
                      "type": "boolean"
                    },
                    "recommended_limit": {
                      "type": "string",
                      "pattern": "^[0-9]{1,15}$",
                      "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits)."
                    },
                    "risk_band": {
                      "type": "string"
                    },
                    "score_factors": {
                      "type": "object"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/accounts/{accountId}/overdraft/recalculate\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/accounts/{accountId}/overdraft/recalculate',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/accounts/{accountId}/overdraft/recalculate\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/accounts/{accountId}/overdraft/recalculate',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/accounts/{accountId}/overdraft/request": {
      "post": {
        "tags": [
          "Overdraft"
        ],
        "summary": "Request overdraft facility",
        "description": "Request an overdraft. Automatically scores the account and either auto-approves (high score) or routes to manager approval.",
        "operationId": "requestOverdraft",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "accountId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "requested_limit": {
                    "type": "number",
                    "example": 300000
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Overdraft auto-approved",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "202": {
            "description": "Pending manager approval",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "string",
                      "example": "pending_approval"
                    },
                    "overdraft_id": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/accounts/{accountId}/overdraft/request\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/accounts/{accountId}/overdraft/request',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/accounts/{accountId}/overdraft/request\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/accounts/{accountId}/overdraft/request',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/accounts/{accountId}/overdraft/approve": {
      "post": {
        "tags": [
          "Overdraft"
        ],
        "summary": "Approve overdraft",
        "operationId": "approveOverdraft",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "accountId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "approved_limit"
                ],
                "properties": {
                  "approved_limit": {
                    "type": "string",
                    "example": "200000",
                    "pattern": "^[0-9]{1,15}$",
                    "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits)."
                  },
                  "comments": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Overdraft approved and activated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Approve overdraft.\n\n**Tag:** Overdraft\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/accounts/{accountId}/overdraft/approve\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/accounts/{accountId}/overdraft/approve',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/accounts/{accountId}/overdraft/approve\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/accounts/{accountId}/overdraft/approve',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/accounts/{accountId}/overdraft/suspend": {
      "post": {
        "tags": [
          "Overdraft"
        ],
        "summary": "Suspend overdraft",
        "operationId": "suspendOverdraft",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "accountId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Recommended for safe retries. UUID v4. When supplied, duplicate requests within 24h replay the original response. See Idempotency guide."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "reason"
                ],
                "properties": {
                  "reason": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Overdraft suspended",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Suspend overdraft.\n\n**Tag:** Overdraft\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/accounts/{accountId}/overdraft/suspend\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/accounts/{accountId}/overdraft/suspend',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/accounts/{accountId}/overdraft/suspend\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/accounts/{accountId}/overdraft/suspend',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/accounts/{accountId}/overdraft/revoke": {
      "post": {
        "tags": [
          "Overdraft"
        ],
        "summary": "Revoke overdraft",
        "operationId": "revokeOverdraft",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "accountId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Recommended for safe retries. UUID v4. When supplied, duplicate requests within 24h replay the original response. See Idempotency guide."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "reason"
                ],
                "properties": {
                  "reason": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Overdraft revoked",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Revoke overdraft.\n\n**Tag:** Overdraft\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/accounts/{accountId}/overdraft/revoke\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/accounts/{accountId}/overdraft/revoke',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/accounts/{accountId}/overdraft/revoke\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/accounts/{accountId}/overdraft/revoke',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/accounts/{accountId}/overdraft/reinstate": {
      "post": {
        "tags": [
          "Overdraft"
        ],
        "summary": "Reinstate overdraft",
        "operationId": "reinstateOverdraft",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "accountId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "new_limit": {
                    "type": "number"
                  },
                  "comments": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Overdraft reinstated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Reinstate overdraft.\n\n**Tag:** Overdraft\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/accounts/{accountId}/overdraft/reinstate\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/accounts/{accountId}/overdraft/reinstate',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/accounts/{accountId}/overdraft/reinstate\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/accounts/{accountId}/overdraft/reinstate',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/wallets": {
      "post": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "Create custodial wallet",
        "operationId": "walletCreate",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "currency"
                ],
                "properties": {
                  "currency": {
                    "type": "string",
                    "default": "XAF",
                    "enum": [
                      "XAF",
                      "XOF",
                      "USD",
                      "EUR",
                      "GBP",
                      "CNY",
                      "NGN",
                      "GHS",
                      "KES",
                      "ZAR"
                    ],
                    "description": "ISO 4217 currency code. Default is XAF (Central African CFA Franc)."
                  },
                  "label": {
                    "type": "string"
                  },
                  "metadata": {
                    "type": "object"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Wallet created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "currency": {
                      "type": "string",
                      "enum": [
                        "XAF",
                        "XOF",
                        "USD",
                        "EUR",
                        "GBP",
                        "CNY",
                        "NGN",
                        "GHS",
                        "KES",
                        "ZAR"
                      ],
                      "default": "XAF",
                      "description": "ISO 4217 currency code. Default is XAF (Central African CFA Franc)."
                    },
                    "available_balance": {
                      "type": "string",
                      "pattern": "^[0-9]{1,15}$",
                      "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits). Must be consistent with the currency field."
                    },
                    "status": {
                      "type": "string"
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Create custodial wallet.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/wallets\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/wallets',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/wallets\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/wallets',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      },
      "get": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "List wallets",
        "operationId": "walletList",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 25,
              "maximum": 100
            },
            "description": "Items per page"
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 0
            },
            "description": "Items to skip"
          },
          {
            "name": "sort_by",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "created_at"
            },
            "description": "Sort field"
          },
          {
            "name": "sort_order",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "asc",
                "desc"
              ],
              "default": "desc"
            },
            "description": "Sort direction"
          },
          {
            "$ref": "#/components/parameters/StartingAfter"
          },
          {
            "$ref": "#/components/parameters/EndingBefore"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Wallets list",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/GatewayMerchantWallet"
                          }
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Cursor-paginated list",
                    "value": {
                      "data": [
                        {
                          "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "merchant_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "currency": "XAF",
                          "available_balance": "500000",
                          "object": "resource",
                          "created_at": "2026-05-02T10:15:30Z"
                        },
                        {
                          "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "merchant_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "currency": "XAF",
                          "available_balance": "500000",
                          "object": "resource",
                          "created_at": "2026-05-02T10:15:31Z"
                        }
                      ],
                      "pagination": {
                        "page": 1,
                        "limit": 20,
                        "total": 150,
                        "has_next": true,
                        "has_more": true,
                        "next_cursor": "cursor_01HZX9TRJ4M7YQK6P3W2VBDN5M",
                        "prev_cursor": null,
                        "total_count": 247
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "List wallets.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/wallets\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/wallets',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/wallets\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/wallets',\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/wallets/{walletId}": {
      "get": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "Get wallet balance",
        "operationId": "walletGet",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "walletId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Wallet with Available, Pending, Ledger balances",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/StandardResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/GatewayMerchantWallet"
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Successful response envelope",
                    "value": {
                      "data": {
                        "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                        "merchant_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                        "currency": "XAF",
                        "available_balance": "500000",
                        "object": "resource",
                        "created_at": "2026-05-02T10:15:30Z"
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Get wallet balance.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/wallets/{walletId}\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/wallets/{walletId}',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/wallets/{walletId}\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/wallets/{walletId}',\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/wallets/{walletId}/credit": {
      "post": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "Credit wallet",
        "operationId": "walletCredit",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "walletId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "amount",
                  "currency"
                ],
                "properties": {
                  "amount": {
                    "type": "string",
                    "pattern": "^[0-9]{1,15}$",
                    "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits). Must be consistent with the currency field."
                  },
                  "currency": {
                    "type": "string",
                    "enum": [
                      "XAF",
                      "XOF",
                      "USD",
                      "EUR",
                      "GBP",
                      "CNY",
                      "NGN",
                      "GHS",
                      "KES",
                      "ZAR"
                    ],
                    "default": "XAF",
                    "description": "ISO 4217 currency code. Default is XAF (Central African CFA Franc)."
                  },
                  "description": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Wallet credited",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Credit wallet.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/wallets/{walletId}/credit\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/wallets/{walletId}/credit',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/wallets/{walletId}/credit\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/wallets/{walletId}/credit',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/wallets/{walletId}/debit": {
      "post": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "Debit wallet",
        "operationId": "walletDebit",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "walletId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "amount",
                  "currency"
                ],
                "properties": {
                  "amount": {
                    "type": "string",
                    "pattern": "^[0-9]{1,15}$",
                    "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits). Must be consistent with the currency field."
                  },
                  "currency": {
                    "type": "string",
                    "enum": [
                      "XAF",
                      "XOF",
                      "USD",
                      "EUR",
                      "GBP",
                      "CNY",
                      "NGN",
                      "GHS",
                      "KES",
                      "ZAR"
                    ],
                    "default": "XAF",
                    "description": "ISO 4217 currency code. Default is XAF (Central African CFA Franc)."
                  },
                  "description": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Wallet debited",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Debit wallet.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/wallets/{walletId}/debit\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/wallets/{walletId}/debit',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/wallets/{walletId}/debit\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/wallets/{walletId}/debit',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/wallets/{walletId}/freeze": {
      "post": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "Freeze/unfreeze wallet",
        "operationId": "walletFreeze",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "walletId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "action"
                ],
                "properties": {
                  "action": {
                    "type": "string",
                    "enum": [
                      "freeze",
                      "unfreeze"
                    ]
                  },
                  "reason": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Wallet frozen/unfrozen",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Freeze/unfreeze wallet.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/wallets/{walletId}/freeze\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/wallets/{walletId}/freeze',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/wallets/{walletId}/freeze\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/wallets/{walletId}/freeze',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/wallets/{walletId}/statement": {
      "get": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "Wallet statement",
        "operationId": "walletStatement",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "walletId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "from",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "to",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 25,
              "maximum": 100
            },
            "description": "Items per page"
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 0
            },
            "description": "Items to skip"
          },
          {
            "name": "sort_by",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "created_at"
            },
            "description": "Sort field"
          },
          {
            "name": "sort_order",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "asc",
                "desc"
              ],
              "default": "desc"
            },
            "description": "Sort direction"
          },
          {
            "$ref": "#/components/parameters/StartingAfter"
          },
          {
            "$ref": "#/components/parameters/EndingBefore"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Wallet transaction history",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {}
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Successful response envelope",
                    "value": {
                      "data": [
                        "data_value"
                      ],
                      "pagination": {
                        "page": 1,
                        "limit": 20,
                        "total": 150,
                        "has_next": true
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Wallet statement.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/wallets/{walletId}/statement\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/wallets/{walletId}/statement',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/wallets/{walletId}/statement\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/wallets/{walletId}/statement',\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/escrow": {
      "post": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "Create escrow hold",
        "operationId": "escrowCreate",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "merchant_id",
                  "amount",
                  "currency"
                ],
                "properties": {
                  "merchant_id": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "amount": {
                    "type": "string",
                    "pattern": "^[0-9]{1,15}$",
                    "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits). Must be consistent with the currency field."
                  },
                  "currency": {
                    "type": "string",
                    "default": "XAF",
                    "enum": [
                      "XAF",
                      "XOF",
                      "USD",
                      "EUR",
                      "GBP",
                      "CNY",
                      "NGN",
                      "GHS",
                      "KES",
                      "ZAR"
                    ],
                    "description": "ISO 4217 currency code. Default is XAF (Central African CFA Franc)."
                  },
                  "description": {
                    "type": "string"
                  },
                  "release_conditions": {
                    "type": "object",
                    "description": "Structured conditions that must be satisfied before the escrow can be released",
                    "properties": {
                      "type": {
                        "type": "string",
                        "enum": [
                          "time_based",
                          "confirmation_based",
                          "milestone_based",
                          "manual"
                        ],
                        "description": "The type of release trigger"
                      },
                      "release_after_date": {
                        "type": "string",
                        "format": "date-time",
                        "description": "For time_based: UTC datetime after which auto-release is permitted"
                      },
                      "required_confirmations": {
                        "type": "integer",
                        "description": "For confirmation_based: number of parties that must confirm before release",
                        "minimum": 1,
                        "maximum": 10
                      },
                      "milestones": {
                        "type": "array",
                        "description": "For milestone_based: list of milestone descriptions that must be marked complete",
                        "items": {
                          "type": "object",
                          "properties": {
                            "id": {
                              "type": "string"
                            },
                            "description": {
                              "type": "string"
                            },
                            "completed": {
                              "type": "boolean",
                              "default": false
                            }
                          }
                        }
                      },
                      "human_readable_summary": {
                        "type": "string",
                        "description": "Plain English description of the release conditions for audit and display purposes"
                      }
                    },
                    "required": [
                      "type",
                      "human_readable_summary"
                    ]
                  },
                  "expires_at": {
                    "type": "string",
                    "format": "date-time"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Escrow created",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/StandardResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "properties": {
                            "id": {
                              "type": "string"
                            },
                            "amount": {
                              "type": "string",
                              "pattern": "^[0-9]{1,15}$",
                              "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits). Must be consistent with the currency field."
                            },
                            "currency": {
                              "type": "string",
                              "enum": [
                                "XAF",
                                "XOF",
                                "USD",
                                "EUR",
                                "GBP",
                                "CNY",
                                "NGN",
                                "GHS",
                                "KES",
                                "ZAR"
                              ],
                              "default": "XAF",
                              "description": "ISO 4217 currency code. Default is XAF (Central African CFA Franc)."
                            },
                            "status": {
                              "type": "string",
                              "example": "active"
                            },
                            "created_at": {
                              "type": "string",
                              "format": "date-time"
                            }
                          }
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Create escrow hold.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/escrow\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/escrow',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/escrow\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/escrow',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      },
      "get": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "List escrow holds",
        "operationId": "escrowList",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "merchant_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "active",
                "released",
                "refunded",
                "frozen",
                "expired"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 25,
              "maximum": 100
            },
            "description": "Items per page"
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 0
            },
            "description": "Items to skip"
          },
          {
            "name": "sort_by",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "created_at"
            },
            "description": "Sort field"
          },
          {
            "name": "sort_order",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "asc",
                "desc"
              ],
              "default": "desc"
            },
            "description": "Sort direction"
          },
          {
            "$ref": "#/components/parameters/StartingAfter"
          },
          {
            "$ref": "#/components/parameters/EndingBefore"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Escrow holds",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {}
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Successful response envelope",
                    "value": {
                      "data": [
                        "data_value"
                      ],
                      "pagination": {
                        "page": 1,
                        "limit": 20,
                        "total": 150,
                        "has_next": true
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "List escrow holds.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/escrow\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/escrow',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/escrow\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/escrow',\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/escrow/{escrowId}/fund": {
      "post": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "Fund escrow",
        "operationId": "escrowFund",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "escrowId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "amount"
                ],
                "properties": {
                  "amount": {
                    "type": "string",
                    "pattern": "^[0-9]{1,15}$",
                    "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits)."
                  },
                  "source_wallet_id": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Escrow funded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Fund escrow.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/escrow/{escrowId}/fund\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/escrow/{escrowId}/fund',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/escrow/{escrowId}/fund\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/escrow/{escrowId}/fund',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/escrow/{escrowId}/release": {
      "post": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "Release escrow",
        "operationId": "escrowRelease",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "escrowId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "amount": {
                    "type": "string",
                    "description": "Partial release amount (omit for full) Represented as a string integer in the currency's minor unit (XAF has no subunits).",
                    "pattern": "^[0-9]{1,15}$"
                  },
                  "recipient_wallet_id": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Escrow released",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Release escrow.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/escrow/{escrowId}/release\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/escrow/{escrowId}/release',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/escrow/{escrowId}/release\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/escrow/{escrowId}/release',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/escrow/{escrowId}/refund": {
      "post": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "Refund escrow",
        "operationId": "escrowRefund",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "escrowId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "reason": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Escrow refunded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Refund escrow.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/escrow/{escrowId}/refund\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/escrow/{escrowId}/refund',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/escrow/{escrowId}/refund\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/escrow/{escrowId}/refund',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/escrow/{escrowId}/freeze": {
      "post": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "Freeze escrow",
        "operationId": "escrowFreeze",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "escrowId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "action"
                ],
                "properties": {
                  "action": {
                    "type": "string",
                    "enum": [
                      "freeze",
                      "unfreeze"
                    ]
                  },
                  "reason": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Escrow frozen/unfrozen",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Freeze escrow.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/escrow/{escrowId}/freeze\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/escrow/{escrowId}/freeze',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/escrow/{escrowId}/freeze\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/escrow/{escrowId}/freeze',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/compliance/screen": {
      "post": {
        "tags": [
          "KYC & Compliance"
        ],
        "summary": "Pre-payout compliance screen",
        "description": "Evaluate transaction against KYC risk scores, sanctions, PEP status, and velocity limits. Returns approve/review/deny.",
        "operationId": "complianceScreen",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "user_id",
                  "amount",
                  "currency"
                ],
                "properties": {
                  "user_id": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "amount": {
                    "type": "string",
                    "pattern": "^[0-9]{1,15}$",
                    "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits). Must be consistent with the currency field."
                  },
                  "currency": {
                    "type": "string",
                    "enum": [
                      "XAF",
                      "XOF",
                      "USD",
                      "EUR",
                      "GBP",
                      "CNY",
                      "NGN",
                      "GHS",
                      "KES",
                      "ZAR"
                    ],
                    "default": "XAF",
                    "description": "ISO 4217 currency code. Default is XAF (Central African CFA Franc)."
                  },
                  "destination_type": {
                    "type": "string"
                  },
                  "destination_country": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Screening decision",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "decision": {
                      "type": "string",
                      "enum": [
                        "approve",
                        "review",
                        "deny"
                      ]
                    },
                    "risk_score": {
                      "type": "integer"
                    },
                    "checks": {
                      "type": "object"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/compliance/screen\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/compliance/screen',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/compliance/screen\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/compliance/screen',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ]
      }
    },
    "/v1/compliance/sar": {
      "post": {
        "tags": [
          "KYC & Compliance"
        ],
        "summary": "File SAR",
        "description": "File SAR.\n\n**Tag:** KYC & Compliance\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "operationId": "sarFile",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "subject_user_id",
                  "activity_type",
                  "description"
                ],
                "properties": {
                  "subject_user_id": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "activity_type": {
                    "type": "string"
                  },
                  "description": {
                    "type": "string"
                  },
                  "amount": {
                    "type": "string",
                    "pattern": "^[0-9]{1,15}$",
                    "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits). Must be consistent with the currency field."
                  },
                  "currency": {
                    "type": "string",
                    "enum": [
                      "XAF",
                      "XOF",
                      "USD",
                      "EUR",
                      "GBP",
                      "CNY",
                      "NGN",
                      "GHS",
                      "KES",
                      "ZAR"
                    ],
                    "default": "XAF",
                    "description": "ISO 4217 currency code. Default is XAF (Central African CFA Franc)."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "SAR filed",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "status": {
                      "type": "string",
                      "example": "filed"
                    },
                    "reference": {
                      "type": "string"
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/compliance/sar\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/compliance/sar',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/compliance/sar\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/compliance/sar',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      },
      "get": {
        "tags": [
          "KYC & Compliance"
        ],
        "summary": "List SARs",
        "operationId": "sarList",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "draft",
                "filed",
                "under_review",
                "escalated",
                "submitted",
                "closed"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 25,
              "maximum": 100
            },
            "description": "Items per page"
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 0
            },
            "description": "Items to skip"
          },
          {
            "name": "sort_by",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "created_at"
            },
            "description": "Sort field"
          },
          {
            "name": "sort_order",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "asc",
                "desc"
              ],
              "default": "desc"
            },
            "description": "Sort direction"
          },
          {
            "$ref": "#/components/parameters/StartingAfter"
          },
          {
            "$ref": "#/components/parameters/EndingBefore"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "SAR list",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {}
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Successful response envelope",
                    "value": {
                      "data": [
                        "data_value"
                      ],
                      "pagination": {
                        "page": 1,
                        "limit": 20,
                        "total": 150,
                        "has_next": true
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "List SARs.\n\n**Tag:** KYC & Compliance\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/compliance/sar\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/compliance/sar',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/compliance/sar\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/compliance/sar',\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/compliance/sar/{sarId}/review": {
      "post": {
        "tags": [
          "KYC & Compliance"
        ],
        "summary": "Review SAR",
        "operationId": "sarReview",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "sarId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "action"
                ],
                "properties": {
                  "action": {
                    "type": "string",
                    "enum": [
                      "approve",
                      "escalate",
                      "close",
                      "request_info"
                    ]
                  },
                  "notes": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "SAR reviewed",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Review SAR.\n\n**Tag:** KYC & Compliance\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/compliance/sar/{sarId}/review\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/compliance/sar/{sarId}/review',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/compliance/sar/{sarId}/review\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/compliance/sar/{sarId}/review',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/compliance/sar/{sarId}/submit": {
      "post": {
        "tags": [
          "KYC & Compliance"
        ],
        "summary": "Submit SAR to regulator",
        "operationId": "sarSubmit",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "sarId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "SAR submitted",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Submit SAR to regulator.\n\n**Tag:** KYC & Compliance\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/compliance/sar/{sarId}/submit\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/compliance/sar/{sarId}/submit',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/compliance/sar/{sarId}/submit\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/compliance/sar/{sarId}/submit',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/safeguarding/reconcile": {
      "post": {
        "tags": [
          "KYC & Compliance"
        ],
        "summary": "Run safeguarding reconciliation",
        "description": "Run safeguarding reconciliation.\n\n**Tag:** KYC & Compliance\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "operationId": "safeguardingReconcile",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Reconciliation result with discrepancy details",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "total_liabilities": {
                      "type": "number",
                      "deprecated": true,
                      "x-successor": "total_liabilities_money",
                      "x-sunset": "5.0.0",
                      "description": "Deprecated: floating-point monetary value (IEEE-754 binary64 cannot represent decimal minor units exactly). Use `total_liabilities_money` instead. Removal is scheduled for v5.0.0."
                    },
                    "total_assets": {
                      "type": "number",
                      "deprecated": true,
                      "x-successor": "total_assets_money",
                      "x-sunset": "5.0.0",
                      "description": "Deprecated: floating-point monetary value (IEEE-754 binary64 cannot represent decimal minor units exactly). Use `total_assets_money` instead. Removal is scheduled for v5.0.0."
                    },
                    "discrepancy": {
                      "type": "number"
                    },
                    "status": {
                      "type": "string"
                    },
                    "total_liabilities_money": {
                      "$ref": "#/components/schemas/Money",
                      "description": "Canonical string-encoded successor to `total_liabilities`. Amount and ISO 4217 currency travel together (ISO 20022 ActiveCurrencyAndAmount). Prefer this field: it is exact for zero-decimal currencies (XAF, XOF) and immune to IEEE-754 drift.",
                      "x-added-in": "4.54.0"
                    },
                    "total_assets_money": {
                      "$ref": "#/components/schemas/Money",
                      "description": "Canonical string-encoded successor to `total_assets`. Amount and ISO 4217 currency travel together (ISO 20022 ActiveCurrencyAndAmount). Prefer this field: it is exact for zero-decimal currencies (XAF, XOF) and immune to IEEE-754 drift.",
                      "x-added-in": "4.54.0"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/safeguarding/reconcile\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/safeguarding/reconcile',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/safeguarding/reconcile\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/safeguarding/reconcile',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ]
      }
    },
    "/v1/safeguarding/snapshots": {
      "get": {
        "tags": [
          "KYC & Compliance"
        ],
        "summary": "List safeguarding snapshots",
        "operationId": "safeguardingSnapshots",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "to",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 25,
              "maximum": 100
            },
            "description": "Items per page"
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 0
            },
            "description": "Items to skip"
          },
          {
            "name": "sort_by",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "created_at"
            },
            "description": "Sort field"
          },
          {
            "name": "sort_order",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "asc",
                "desc"
              ],
              "default": "desc"
            },
            "description": "Sort direction"
          },
          {
            "$ref": "#/components/parameters/StartingAfter"
          },
          {
            "$ref": "#/components/parameters/EndingBefore"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Daily safeguarding snapshots",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {}
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Cursor-paginated list",
                    "value": {
                      "data": [
                        "data_value",
                        "data_value"
                      ],
                      "pagination": {
                        "page": 1,
                        "limit": 20,
                        "total": 150,
                        "has_next": true,
                        "has_more": true,
                        "next_cursor": "cursor_01HZX9TRJ4M7YQK6P3W2VBDN5M",
                        "prev_cursor": null,
                        "total_count": 247
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "List safeguarding snapshots.\n\n**Tag:** KYC & Compliance\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/safeguarding/snapshots\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/safeguarding/snapshots',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/safeguarding/snapshots\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/safeguarding/snapshots',\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/payouts/instant": {
      "post": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "Instant payout",
        "description": "Route payout through fastest available rail (MoMo instant, bank express, Visa Direct).",
        "operationId": "payoutInstant",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "merchant_id",
                  "amount",
                  "currency",
                  "channel"
                ],
                "properties": {
                  "merchant_id": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "amount": {
                    "type": "string",
                    "pattern": "^[0-9]{1,15}$",
                    "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits). Must be consistent with the currency field."
                  },
                  "currency": {
                    "type": "string",
                    "enum": [
                      "XAF",
                      "XOF",
                      "USD",
                      "EUR",
                      "GBP",
                      "CNY",
                      "NGN",
                      "GHS",
                      "KES",
                      "ZAR"
                    ],
                    "default": "XAF",
                    "description": "ISO 4217 currency code. Default is XAF (Central African CFA Franc)."
                  },
                  "channel": {
                    "type": "string",
                    "enum": [
                      "momo_instant",
                      "bank_express",
                      "visa_direct"
                    ]
                  },
                  "beneficiary_phone": {
                    "type": "string"
                  },
                  "beneficiary_account": {
                    "type": "string"
                  },
                  "beneficiary_name": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Instant payout initiated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewayPayout"
                },
                "examples": {
                  "default": {
                    "summary": "Successful response envelope",
                    "value": {
                      "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                      "merchant_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                      "amount": "10000",
                      "currency": "XAF",
                      "channel": "mobile_money",
                      "status": "pending",
                      "created_at": "2026-05-02T10:15:30Z",
                      "success": true,
                      "data": {
                        "id": "obj_01HZX9TRJ4M7YQK6P3W2VBDN5K",
                        "object": "resource",
                        "created_at": "2026-05-02T10:15:30Z"
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      }
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/payouts/instant\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/payouts/instant',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/payouts/instant\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/payouts/instant',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/payouts/push-to-card": {
      "post": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "Push-to-card payout",
        "description": "Push-to-card payout.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "operationId": "payoutPushToCard",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "merchant_id",
                  "amount",
                  "currency",
                  "card_number"
                ],
                "properties": {
                  "merchant_id": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "amount": {
                    "type": "string",
                    "pattern": "^[0-9]{1,15}$",
                    "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits). Must be consistent with the currency field."
                  },
                  "currency": {
                    "type": "string",
                    "enum": [
                      "XAF",
                      "XOF",
                      "USD",
                      "EUR",
                      "GBP",
                      "CNY",
                      "NGN",
                      "GHS",
                      "KES",
                      "ZAR"
                    ],
                    "default": "XAF",
                    "description": "ISO 4217 currency code. Default is XAF (Central African CFA Franc)."
                  },
                  "card_number": {
                    "type": "string"
                  },
                  "card_holder_name": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Push-to-card initiated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewayPayout"
                },
                "examples": {
                  "default": {
                    "summary": "Successful response envelope",
                    "value": {
                      "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                      "merchant_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                      "amount": "10000",
                      "currency": "XAF",
                      "channel": "mobile_money",
                      "status": "pending",
                      "created_at": "2026-05-02T10:15:30Z",
                      "success": true,
                      "data": {
                        "id": "obj_01HZX9TRJ4M7YQK6P3W2VBDN5K",
                        "object": "resource",
                        "created_at": "2026-05-02T10:15:30Z"
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      }
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/payouts/push-to-card\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/payouts/push-to-card',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/payouts/push-to-card\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/payouts/push-to-card',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ],
        "x-pci-scope": "cardholder_data",
        "x-pci-note": "Accepts a full PAN on the wire to fund a push-to-card payout. The PAN is forwarded to Kora and never persisted in KOB's datastore. Step-up MFA, idempotency, and per-principal rate limits apply."
      }
    },
    "/v1/payouts/rails": {
      "get": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "List available payout rails",
        "description": "List available payout rails.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "operationId": "payoutRails",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "country",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "currency",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/LimitParam"
          },
          {
            "$ref": "#/components/parameters/CursorParam"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Available payout rails with speeds and fees",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {}
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Cursor-paginated list",
                    "value": {
                      "data": [
                        "data_value",
                        "data_value"
                      ],
                      "pagination": {
                        "page": 1,
                        "limit": 20,
                        "total": 150,
                        "has_next": true,
                        "has_more": true,
                        "next_cursor": "cursor_01HZX9TRJ4M7YQK6P3W2VBDN5M",
                        "prev_cursor": null,
                        "total_count": 247
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/payouts/rails\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/payouts/rails',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/payouts/rails\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/payouts/rails',\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/payouts/{payoutId}/cancel": {
      "post": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "Cancel pending payout",
        "operationId": "payoutCancel",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "payoutId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "reason": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Payout cancelled and funds returned to wallet",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Cancel pending payout.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/payouts/{payoutId}/cancel\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/payouts/{payoutId}/cancel',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/payouts/{payoutId}/cancel\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/payouts/{payoutId}/cancel',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/treasury/float": {
      "get": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "Get treasury float balance",
        "description": "Get treasury float balance.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "operationId": "treasuryFloat",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Float balances by provider and currency",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "balances": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "provider": {
                            "type": "string"
                          },
                          "currency": {
                            "type": "string",
                            "enum": [
                              "XAF",
                              "XOF",
                              "USD",
                              "EUR",
                              "GBP",
                              "CNY",
                              "NGN",
                              "GHS",
                              "KES",
                              "ZAR"
                            ],
                            "default": "XAF",
                            "description": "ISO 4217 currency code. Default is XAF (Central African CFA Franc)."
                          },
                          "balance": {
                            "type": "string",
                            "pattern": "^[0-9]{1,15}$",
                            "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits). Must be consistent with the currency field."
                          }
                        }
                      }
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/treasury/float\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/treasury/float',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/treasury/float\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/treasury/float',\n]);\n\nprint_r($response->data);"
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ]
      }
    },
    "/v1/treasury/replenish": {
      "post": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "Replenish treasury float",
        "operationId": "treasuryReplenish",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "provider",
                  "amount",
                  "currency"
                ],
                "properties": {
                  "provider": {
                    "type": "string"
                  },
                  "amount": {
                    "type": "string",
                    "pattern": "^[0-9]{1,15}$",
                    "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits). Must be consistent with the currency field."
                  },
                  "currency": {
                    "type": "string",
                    "enum": [
                      "XAF",
                      "XOF",
                      "USD",
                      "EUR",
                      "GBP",
                      "CNY",
                      "NGN",
                      "GHS",
                      "KES",
                      "ZAR"
                    ],
                    "default": "XAF",
                    "description": "ISO 4217 currency code. Default is XAF (Central African CFA Franc)."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Replenishment initiated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Replenish treasury float.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/treasury/replenish\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/treasury/replenish',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/treasury/replenish\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/treasury/replenish',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/sla/metrics": {
      "get": {
        "tags": [
          "Monitoring"
        ],
        "summary": "SLA metrics",
        "description": "SLA metrics.\n\n**Tag:** Monitoring\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "operationId": "slaMetrics",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "to",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "$ref": "#/components/parameters/LimitParam"
          },
          {
            "$ref": "#/components/parameters/CursorParam"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "SLA metric data",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {}
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Cursor-paginated list",
                    "value": {
                      "data": [
                        "data_value",
                        "data_value"
                      ],
                      "pagination": {
                        "page": 1,
                        "limit": 20,
                        "total": 150,
                        "has_next": true,
                        "has_more": true,
                        "next_cursor": "cursor_01HZX9TRJ4M7YQK6P3W2VBDN5M",
                        "prev_cursor": null,
                        "total_count": 247
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/sla/metrics\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/sla/metrics',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/sla/metrics\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/sla/metrics',\n]);\n\nprint_r($response->data);"
          }
        ]
      },
      "post": {
        "tags": [
          "Monitoring"
        ],
        "summary": "Record SLA metric",
        "operationId": "slaMetricRecord",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "service_name"
                ],
                "properties": {
                  "service_name": {
                    "type": "string"
                  },
                  "uptime_pct": {
                    "type": "number"
                  },
                  "p50_ms": {
                    "type": "number"
                  },
                  "p95_ms": {
                    "type": "number"
                  },
                  "p99_ms": {
                    "type": "number"
                  },
                  "error_rate": {
                    "type": "number"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Metric recorded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Record SLA metric.\n\n**Tag:** Monitoring\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/sla/metrics\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/sla/metrics',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/sla/metrics\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/sla/metrics',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ]
      }
    },
    "/v1/sla/incidents": {
      "get": {
        "tags": [
          "Monitoring"
        ],
        "summary": "List incidents",
        "operationId": "slaIncidentList",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "open",
                "investigating",
                "resolved"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 25,
              "maximum": 100
            },
            "description": "Items per page"
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 0
            },
            "description": "Items to skip"
          },
          {
            "name": "sort_by",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "created_at"
            },
            "description": "Sort field"
          },
          {
            "name": "sort_order",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "asc",
                "desc"
              ],
              "default": "desc"
            },
            "description": "Sort direction"
          },
          {
            "$ref": "#/components/parameters/StartingAfter"
          },
          {
            "$ref": "#/components/parameters/EndingBefore"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Incident list",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {}
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Cursor-paginated list",
                    "value": {
                      "data": [
                        "data_value",
                        "data_value"
                      ],
                      "pagination": {
                        "page": 1,
                        "limit": 20,
                        "total": 150,
                        "has_next": true,
                        "has_more": true,
                        "next_cursor": "cursor_01HZX9TRJ4M7YQK6P3W2VBDN5M",
                        "prev_cursor": null,
                        "total_count": 247
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "List incidents.\n\n**Tag:** Monitoring\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/sla/incidents\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/sla/incidents',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/sla/incidents\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/sla/incidents',\n]);\n\nprint_r($response->data);"
          }
        ]
      },
      "post": {
        "tags": [
          "Monitoring"
        ],
        "summary": "Create incident",
        "operationId": "slaIncidentCreate",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "title",
                  "severity"
                ],
                "properties": {
                  "title": {
                    "type": "string"
                  },
                  "description": {
                    "type": "string"
                  },
                  "severity": {
                    "type": "string",
                    "enum": [
                      "low",
                      "medium",
                      "high",
                      "critical"
                    ]
                  },
                  "affected_services": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Incident created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "title": {
                      "type": "string"
                    },
                    "severity": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Create incident.\n\n**Tag:** Monitoring\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/sla/incidents\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/sla/incidents',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/sla/incidents\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/sla/incidents',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ]
      }
    },
    "/v1/sla/incidents/{incidentId}": {
      "patch": {
        "tags": [
          "Monitoring"
        ],
        "summary": "Update incident",
        "operationId": "slaIncidentUpdate",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "incidentId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "status": {
                    "type": "string",
                    "enum": [
                      "investigating",
                      "resolved"
                    ]
                  },
                  "resolution_notes": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Incident updated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Update incident.\n\n**Tag:** Monitoring\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X PATCH \"https://api.kangopenbanking.com/v1/sla/incidents/{incidentId}\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'PATCH',\n  path: '/v1/sla/incidents/{incidentId}',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"PATCH\",\n    path=\"/v1/sla/incidents/{incidentId}\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'PATCH',\n    'path'   => '/v1/sla/incidents/{incidentId}',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/webhooks/v2/endpoints": {
      "post": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Register webhook endpoint (v2)",
        "description": "Register a new webhook endpoint with event filtering and unique signing secret. All delivered webhook payloads follow the WebhookEventPayload schema (see components/schemas/WebhookEventPayload). The data field contains the event-specific resource object referenced in the event type mapping.",
        "operationId": "webhookV2Create",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "merchant_id",
                  "url",
                  "events"
                ],
                "properties": {
                  "merchant_id": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "url": {
                    "type": "string",
                    "format": "uri"
                  },
                  "events": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "wildcard.*",
                        "charge.created",
                        "charge.captured",
                        "charge.voided",
                        "charge.failed",
                        "charge.cancelled",
                        "refund.created",
                        "refund.processed",
                        "refund.failed",
                        "payout.created",
                        "payout.processing",
                        "payout.completed",
                        "payout.failed",
                        "payment.initiated",
                        "payment.authorised",
                        "payment.submitted",
                        "payment.completed",
                        "payment.rejected",
                        "payment.cancelled",
                        "dispute.created",
                        "dispute.evidence_required",
                        "dispute.resolved",
                        "settlement.created",
                        "settlement.processed",
                        "consent.authorised",
                        "consent.revoked",
                        "consent.expired",
                        "loan.applied",
                        "loan.approved",
                        "loan.disbursed",
                        "loan.repaid",
                        "loan.defaulted",
                        "kyc.submitted",
                        "kyc.approved",
                        "kyc.rejected",
                        "mobile_money.charge_initiated",
                        "mobile_money.charge_completed",
                        "mobile_money.charge_failed",
                        "escrow.funded",
                        "escrow.released",
                        "escrow.refunded",
                        "virtual_account.credited",
                        "interbank.payment_submitted",
                        "interbank.payment_completed",
                        "interbank.payment_returned",
                        "pay_by_bank.intent_authorised",
                        "pay_by_bank.intent_rejected",
                        "pay_by_bank.payment_completed",
                        "subscription.created",
                        "subscription.renewed",
                        "subscription.cancelled",
                        "subscription.payment_failed"
                      ]
                    },
                    "description": "List of event types to subscribe to. Use 'wildcard.*' to subscribe to all events.",
                    "minItems": 1,
                    "example": [
                      "charge.created",
                      "charge.captured",
                      "refund.created"
                    ]
                  },
                  "description": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Endpoint created with signing secret (shown once)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "url": {
                      "type": "string"
                    },
                    "secret": {
                      "type": "string",
                      "description": "whsec_... — shown only on creation"
                    },
                    "events": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/webhooks/v2/endpoints\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/webhooks/v2/endpoints',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/webhooks/v2/endpoints\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/webhooks/v2/endpoints',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      },
      "get": {
        "tags": [
          "Webhooks"
        ],
        "summary": "List webhook endpoints (v2)",
        "operationId": "webhookV2List",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "merchant_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/LimitParam"
          },
          {
            "$ref": "#/components/parameters/CursorParam"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Webhook endpoints",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {}
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Cursor-paginated list",
                    "value": {
                      "data": [
                        "data_value",
                        "data_value"
                      ],
                      "pagination": {
                        "page": 1,
                        "limit": 20,
                        "total": 150,
                        "has_next": true,
                        "has_more": true,
                        "next_cursor": "cursor_01HZX9TRJ4M7YQK6P3W2VBDN5M",
                        "prev_cursor": null,
                        "total_count": 247
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "List webhook endpoints (v2).\n\n**Tag:** Webhooks\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/webhooks/v2/endpoints\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/webhooks/v2/endpoints',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/webhooks/v2/endpoints\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/webhooks/v2/endpoints',\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/webhooks/v2/endpoints/{endpointId}": {
      "patch": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Update webhook endpoint",
        "operationId": "webhookV2Update",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "endpointId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "url": {
                    "type": "string"
                  },
                  "events": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "is_active": {
                    "type": "boolean"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Endpoint updated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Update webhook endpoint.\n\n**Tag:** Webhooks\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X PATCH \"https://api.kangopenbanking.com/v1/webhooks/v2/endpoints/{endpointId}\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'PATCH',\n  path: '/v1/webhooks/v2/endpoints/{endpointId}',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"PATCH\",\n    path=\"/v1/webhooks/v2/endpoints/{endpointId}\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'PATCH',\n    'path'   => '/v1/webhooks/v2/endpoints/{endpointId}',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      },
      "delete": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Delete webhook endpoint",
        "operationId": "webhookV2Delete",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "endpointId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "204": {
            "description": "Endpoint deleted",
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            },
            "content": {
              "application/json": {
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Delete webhook endpoint.\n\n**Tag:** Webhooks\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X DELETE \"https://api.kangopenbanking.com/v1/webhooks/v2/endpoints/{endpointId}\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'DELETE',\n  path: '/v1/webhooks/v2/endpoints/{endpointId}',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"DELETE\",\n    path=\"/v1/webhooks/v2/endpoints/{endpointId}\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'DELETE',\n    'path'   => '/v1/webhooks/v2/endpoints/{endpointId}',\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/webhooks/v2/deliveries": {
      "get": {
        "tags": [
          "Webhooks"
        ],
        "summary": "List webhook deliveries",
        "description": "List webhook deliveries.\n\n**Tag:** Webhooks\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "operationId": "webhookV2Deliveries",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "endpoint_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "pending",
                "delivered",
                "failed"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 25,
              "maximum": 100
            },
            "description": "Items per page"
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 0
            },
            "description": "Items to skip"
          },
          {
            "name": "sort_by",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "created_at"
            },
            "description": "Sort field"
          },
          {
            "name": "sort_order",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "asc",
                "desc"
              ],
              "default": "desc"
            },
            "description": "Sort direction"
          },
          {
            "$ref": "#/components/parameters/StartingAfter"
          },
          {
            "$ref": "#/components/parameters/EndingBefore"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Delivery logs",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {}
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Cursor-paginated list",
                    "value": {
                      "data": [
                        "data_value",
                        "data_value"
                      ],
                      "pagination": {
                        "page": 1,
                        "limit": 20,
                        "total": 150,
                        "has_next": true,
                        "has_more": true,
                        "next_cursor": "cursor_01HZX9TRJ4M7YQK6P3W2VBDN5M",
                        "prev_cursor": null,
                        "total_count": 247
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/webhooks/v2/deliveries\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/webhooks/v2/deliveries',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/webhooks/v2/deliveries\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/webhooks/v2/deliveries',\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/webhooks/v2/endpoints/{endpointId}/deliveries/{deliveryId}/replay": {
      "post": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Replay a single webhook delivery",
        "description": "Re-send the original payload of a previously attempted delivery to the same endpoint. A new delivery record is created (one-shot, no automatic retry) so the original audit trail is preserved. Useful when a downstream service was temporarily unavailable. Justification: Stripe webhook reliability parity; FAPI-1.0-Adv §6.2 (delivery accountability).",
        "operationId": "webhookV2ReplayDelivery",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "endpointId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "deliveryId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookReplayRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Replay attempted; new delivery record returned",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookReplayResult"
                },
                "examples": {
                  "default": {
                    "summary": "Successful response envelope",
                    "value": {
                      "replay_delivery_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                      "original_delivery_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                      "endpoint_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                      "status": "delivered",
                      "created_at": "2026-05-02T10:15:30Z",
                      "success": true,
                      "data": {
                        "id": "obj_01HZX9TRJ4M7YQK6P3W2VBDN5K",
                        "object": "resource",
                        "created_at": "2026-05-02T10:15:30Z"
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      }
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          },
          "404": {
            "description": "Endpoint or delivery not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          },
          "409": {
            "description": "Endpoint inactive",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/webhooks/v2/endpoints/{endpointId}/deliveries/{deliveryId}/replay\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/webhooks/v2/endpoints/{endpointId}/deliveries/{deliveryId}/replay',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/webhooks/v2/endpoints/{endpointId}/deliveries/{deliveryId}/replay\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/webhooks/v2/endpoints/{endpointId}/deliveries/{deliveryId}/replay',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/webhooks/v2/endpoints/{endpointId}/health": {
      "get": {
        "tags": [
          "Webhooks"
        ],
        "summary": "Get webhook endpoint health snapshot",
        "description": "Return a 24-hour health snapshot for an endpoint: success rate, latency percentiles (p50/p95/p99), totals by status, and last delivery / failure timestamps. Justification: PSD2 RTS Article 32 (operational monitoring); Stripe/PayPal endpoint health parity.",
        "operationId": "webhookV2EndpointHealth",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "endpointId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Health snapshot",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookEndpointHealth"
                },
                "examples": {
                  "default": {
                    "summary": "Successful response envelope",
                    "value": {
                      "endpoint_id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                      "url": "https://api.kangopenbanking.com/v1/resource/3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                      "is_active": true,
                      "window": "24h",
                      "health": "healthy",
                      "totals": {
                        "total": 0,
                        "delivered": 0,
                        "failed": 0,
                        "pending": 0,
                        "exhausted": 0
                      },
                      "generated_at": "2026-05-02T10:15:30Z",
                      "success": true,
                      "data": {
                        "id": "obj_01HZX9TRJ4M7YQK6P3W2VBDN5K",
                        "object": "resource",
                        "created_at": "2026-05-02T10:15:30Z"
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      }
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          },
          "404": {
            "description": "Endpoint not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/webhooks/v2/endpoints/{endpointId}/health\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/webhooks/v2/endpoints/{endpointId}/health',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/webhooks/v2/endpoints/{endpointId}/health\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/webhooks/v2/endpoints/{endpointId}/health',\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/sandbox/payout-sim": {
      "post": {
        "tags": [
          "Sandbox"
        ],
        "summary": "Simulate payout scenario",
        "description": "Run a payout through a pre-seeded sandbox scenario (e.g. insufficient_funds, network_timeout, reversed_after_success).",
        "operationId": "sandboxPayoutSim",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "scenario",
                  "amount",
                  "currency"
                ],
                "properties": {
                  "scenario": {
                    "type": "string",
                    "enum": [
                      "instant_success",
                      "delayed_success",
                      "insufficient_funds",
                      "network_timeout",
                      "compliance_hold",
                      "reversed_after_success",
                      "partial_failure"
                    ]
                  },
                  "amount": {
                    "type": "string",
                    "pattern": "^[0-9]{1,15}$",
                    "description": "Represented as a string integer in the currency's minor unit (XAF has no subunits). Must be consistent with the currency field."
                  },
                  "currency": {
                    "type": "string",
                    "enum": [
                      "XAF",
                      "XOF",
                      "USD",
                      "EUR",
                      "GBP",
                      "CNY",
                      "NGN",
                      "GHS",
                      "KES",
                      "ZAR"
                    ],
                    "default": "XAF",
                    "description": "ISO 4217 currency code. Default is XAF (Central African CFA Franc)."
                  },
                  "merchant_id": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "webhook_url": {
                    "type": "string",
                    "format": "uri"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Simulation result with timeline and webhook callbacks",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "scenario": {
                      "type": "string"
                    },
                    "payout": {
                      "$ref": "#/components/schemas/GatewayPayout"
                    },
                    "timeline": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "event": {
                            "type": "string"
                          },
                          "timestamp": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/sandbox/payout-sim\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/sandbox/payout-sim',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/sandbox/payout-sim\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/sandbox/payout-sim',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      },
      "get": {
        "tags": [
          "Sandbox"
        ],
        "summary": "List sandbox scenarios",
        "operationId": "sandboxScenarioList",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Available sandbox payout scenarios",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {}
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Successful response envelope",
                    "value": {
                      "data": [
                        "data_value"
                      ],
                      "pagination": {
                        "page": 1,
                        "limit": 20,
                        "total": 150,
                        "has_next": true
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/LimitParam"
          },
          {
            "$ref": "#/components/parameters/CursorParam"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "description": "List sandbox scenarios.\n\n**Tag:** Sandbox\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/sandbox/payout-sim\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/sandbox/payout-sim',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/sandbox/payout-sim\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/sandbox/payout-sim',\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/reconciliation/mismatches": {
      "get": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "List reconciliation mismatches",
        "operationId": "reconciliationMismatches",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "merchant_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "open",
                "resolved",
                "ignored"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 25,
              "maximum": 100
            },
            "description": "Items per page"
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 0
            },
            "description": "Items to skip"
          },
          {
            "name": "sort_by",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "created_at"
            },
            "description": "Sort field"
          },
          {
            "name": "sort_order",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "asc",
                "desc"
              ],
              "default": "desc"
            },
            "description": "Sort direction"
          },
          {
            "$ref": "#/components/parameters/StartingAfter"
          },
          {
            "$ref": "#/components/parameters/EndingBefore"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Mismatch list",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {}
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Cursor-paginated list",
                    "value": {
                      "data": [
                        "data_value",
                        "data_value"
                      ],
                      "pagination": {
                        "page": 1,
                        "limit": 20,
                        "total": 150,
                        "has_next": true,
                        "has_more": true,
                        "next_cursor": "cursor_01HZX9TRJ4M7YQK6P3W2VBDN5M",
                        "prev_cursor": null,
                        "total_count": 247
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "List reconciliation mismatches.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/reconciliation/mismatches\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/reconciliation/mismatches',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/reconciliation/mismatches\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/reconciliation/mismatches',\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/reconciliation/mismatches/{mismatchId}/resolve": {
      "post": {
        "tags": [
          "Payment Gateway"
        ],
        "summary": "Resolve mismatch",
        "operationId": "reconciliationResolve",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "mismatchId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Recommended for safe retries. UUID v4. When supplied, duplicate requests within 24h replay the original response. See Idempotency guide."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "resolution"
                ],
                "properties": {
                  "resolution": {
                    "type": "string",
                    "enum": [
                      "adjust_ledger",
                      "adjust_provider",
                      "ignore"
                    ]
                  },
                  "notes": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Mismatch resolved",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "X-Idempotent-Replay": {
                "$ref": "#/components/headers/X-Idempotent-Replay"
              },
              "X-Idempotency-Status": {
                "$ref": "#/components/headers/X-Idempotency-Status"
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Resolve mismatch.\n\n**Tag:** Payment Gateway\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/reconciliation/mismatches/{mismatchId}/resolve\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/reconciliation/mismatches/{mismatchId}/resolve',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/reconciliation/mismatches/{mismatchId}/resolve\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/reconciliation/mismatches/{mismatchId}/resolve',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/directory/banks": {
      "get": {
        "tags": [
          "Bank Directory"
        ],
        "summary": "List active banks",
        "description": "List active banks.\n\n**Tag:** Bank Directory\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "operationId": "directoryBanksList",
        "responses": {
          "200": {
            "description": "List of active banks",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "banks": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Bank"
                      }
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/PaginatedList"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/directory/banks\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/directory/banks',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/directory/banks\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/directory/banks',\n]);\n\nprint_r($response->data);"
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          },
          {
            "$ref": "#/components/parameters/LimitParam"
          },
          {
            "$ref": "#/components/parameters/CursorParam"
          }
        ]
      }
    },
    "/v1/banks/register": {
      "post": {
        "tags": [
          "Bank Directory"
        ],
        "summary": "Register a bank",
        "description": "Register a bank.\n\n**Tag:** Bank Directory\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "operationId": "bankRegister",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Required on all POST/PUT endpoints. Unique key for idempotent request processing (UUID v4 recommended). Keys expire after 24 hours."
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "legal_name",
                  "short_code"
                ],
                "properties": {
                  "legal_name": {
                    "type": "string",
                    "example": "Afriland First Bank"
                  },
                  "display_name": {
                    "type": "string"
                  },
                  "short_code": {
                    "type": "string",
                    "example": "AFB"
                  },
                  "swift_bic": {
                    "type": "string"
                  },
                  "bank_code": {
                    "type": "string"
                  },
                  "contact_email": {
                    "type": "string"
                  },
                  "support_phone": {
                    "type": "string"
                  },
                  "integration_mode": {
                    "type": "string",
                    "enum": [
                      "connector_push",
                      "connector_pull",
                      "file_feed",
                      "hybrid"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Bank registered",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Bank"
                },
                "examples": {
                  "default": {
                    "summary": "Successful response envelope",
                    "value": {
                      "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                      "legal_name": "Afriland First Bank",
                      "short_code": "AFB",
                      "country": "country_value",
                      "success": true,
                      "data": {
                        "id": "obj_01HZX9TRJ4M7YQK6P3W2VBDN5K",
                        "object": "resource",
                        "created_at": "2026-05-02T10:15:30Z"
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      }
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/banks/register\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/banks/register',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/banks/register\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/banks/register',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/banks": {
      "get": {
        "tags": [
          "Bank Directory"
        ],
        "summary": "List all banks (admin)",
        "description": "List all banks (admin).\n\n**Tag:** Bank Directory\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "operationId": "banksList",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 25,
              "maximum": 100
            },
            "description": "Items per page"
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 0
            },
            "description": "Items to skip"
          },
          {
            "name": "sort_by",
            "in": "query",
            "schema": {
              "type": "string",
              "default": "created_at"
            },
            "description": "Sort field"
          },
          {
            "name": "sort_order",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "asc",
                "desc"
              ],
              "default": "desc"
            },
            "description": "Sort direction"
          },
          {
            "$ref": "#/components/parameters/StartingAfter"
          },
          {
            "$ref": "#/components/parameters/EndingBefore"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Banks list",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/Bank"
                          }
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Cursor-paginated list",
                    "value": {
                      "data": [
                        {
                          "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "legal_name": "Afriland First Bank",
                          "short_code": "AFB",
                          "country": "country_value",
                          "object": "resource",
                          "created_at": "2026-05-02T10:15:30Z"
                        },
                        {
                          "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                          "legal_name": "Afriland First Bank",
                          "short_code": "AFB",
                          "country": "country_value",
                          "object": "resource",
                          "created_at": "2026-05-02T10:15:31Z"
                        }
                      ],
                      "pagination": {
                        "page": 1,
                        "limit": 20,
                        "total": 150,
                        "has_next": true,
                        "has_more": true,
                        "next_cursor": "cursor_01HZX9TRJ4M7YQK6P3W2VBDN5M",
                        "prev_cursor": null,
                        "total_count": 247
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/banks\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/banks',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/banks\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/banks',\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/banks/{bankId}": {
      "get": {
        "tags": [
          "Bank Directory"
        ],
        "summary": "Get bank details",
        "operationId": "banksGet",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "bankId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Bank details",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/StandardResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/Bank"
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Successful response envelope",
                    "value": {
                      "data": {
                        "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                        "legal_name": "Afriland First Bank",
                        "short_code": "AFB",
                        "country": "country_value",
                        "object": "resource",
                        "created_at": "2026-05-02T10:15:30Z"
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Get bank details.\n\n**Tag:** Bank Directory\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/banks/{bankId}\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/banks/{bankId}',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/banks/{bankId}\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/banks/{bankId}',\n]);\n\nprint_r($response->data);"
          }
        ]
      },
      "put": {
        "tags": [
          "Bank Directory"
        ],
        "summary": "Update bank",
        "operationId": "banksUpdate",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "bankId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "display_name": {
                    "type": "string"
                  },
                  "contact_email": {
                    "type": "string"
                  },
                  "support_phone": {
                    "type": "string"
                  },
                  "integration_mode": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Bank updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Bank"
                },
                "examples": {
                  "default": {
                    "summary": "Successful response envelope",
                    "value": {
                      "id": "3f1a6b52-9c84-4d2e-8f77-1b0c5a9e4d31",
                      "legal_name": "Afriland First Bank",
                      "short_code": "AFB",
                      "country": "country_value",
                      "success": true,
                      "data": {
                        "id": "obj_01HZX9TRJ4M7YQK6P3W2VBDN5K",
                        "object": "resource",
                        "created_at": "2026-05-02T10:15:30Z"
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      }
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Update bank.\n\n**Tag:** Bank Directory\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X PUT \"https://api.kangopenbanking.com/v1/banks/{bankId}\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'PUT',\n  path: '/v1/banks/{bankId}',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"PUT\",\n    path=\"/v1/banks/{bankId}\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'PUT',\n    'path'   => '/v1/banks/{bankId}',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/banks/{bankId}/approve": {
      "post": {
        "tags": [
          "Bank Directory"
        ],
        "summary": "Approve bank (admin)",
        "operationId": "bankApprove",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "bankId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Bank approved and set to active",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Approve bank (admin).\n\n**Tag:** Bank Directory\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/banks/{bankId}/approve\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/banks/{bankId}/approve',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/banks/{bankId}/approve\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/banks/{bankId}/approve',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/banks/{bankId}/suspend": {
      "post": {
        "tags": [
          "Bank Directory"
        ],
        "summary": "Suspend bank (admin)",
        "operationId": "bankSuspend",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "bankId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Bank suspended",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "example": true
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/GenericSuccess"
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "Suspend bank (admin).\n\n**Tag:** Bank Directory\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X POST \"https://api.kangopenbanking.com/v1/banks/{bankId}/suspend\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\" \\\n  -H \"Idempotency-Key: $(uuidgen)\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"amount\":\"5000\",\"currency\":\"XAF\"}'"
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'POST',\n  path: '/v1/banks/{bankId}/suspend',\n  body: { amount: '5000', currency: 'XAF' },\n  idempotencyKey: crypto.randomUUID(),\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"POST\",\n    path=\"/v1/banks/{bankId}/suspend\",\n    body={\"amount\": \"5000\", \"currency\": \"XAF\"},\n    idempotency_key=str(uuid.uuid4()),\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'POST',\n    'path'   => '/v1/banks/{bankId}/suspend',\n    'body'   => ['amount' => '5000', 'currency' => 'XAF'],\n    'idempotency_key' => \\Ramsey\\Uuid\\Uuid::uuid4()->toString(),\n]);\n\nprint_r($response->data);"
          }
        ]
      }
    },
    "/v1/banks/{bankId}/connectors": {
      "get": {
        "tags": [
          "Bank Connectors"
        ],
        "summary": "List connectors",
        "operationId": "connectorsList",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "bankId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "$ref": "#/components/parameters/LimitParam"
          },
          {
            "$ref": "#/components/parameters/CursorParam"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          },
          {
            "$ref": "#/components/parameters/Traceparent"
          },
          {
            "$ref": "#/components/parameters/Tracestate"
          },
          {
            "$ref": "#/components/parameters/AcceptLanguage"
          }
        ],
        "responses": {
          "200": {
            "description": "Connector instances list",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/PaginatedResponse"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {}
                        }
                      }
                    }
                  ]
                },
                "examples": {
                  "default": {
                    "summary": "Cursor-paginated list",
                    "value": {
                      "data": [
                        "data_value",
                        "data_value"
                      ],
                      "pagination": {
                        "page": 1,
                        "limit": 20,
                        "total": 150,
                        "has_next": true,
                        "has_more": true,
                        "next_cursor": "cursor_01HZX9TRJ4M7YQK6P3W2VBDN5M",
                        "prev_cursor": null,
                        "total_count": 247
                      },
                      "meta": {
                        "request_id": "7d1f0a1c-2b4e-4f6a-9c3d-5e8f0a1b2c3d",
                        "timestamp": "2026-05-02T10:15:30Z"
                      },
                      "success": true
                    }
                  }
                }
              }
            },
            "headers": {
              "x-fapi-interaction-id": {
                "$ref": "#/components/headers/XFapiInteractionIdResponse"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "ETag": {
                "$ref": "#/components/headers/ETag"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              },
              "traceparent": {
                "$ref": "#/components/headers/Traceparent"
              },
              "Content-Language": {
                "$ref": "#/components/headers/Content-Language"
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorBadRequest"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorUnauthorized"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorForbidden"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorNotFound"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "409": {
            "description": "Conflict (idempotency mismatch)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorConflict"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Number of seconds to wait before retrying"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorRateLimited"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "examples": {
                  "default": {
                    "$ref": "#/components/examples/ErrorServer"
                  }
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Trace-Id": {
                "description": "Distributed trace identifier for this request. Echoes the inbound X-Trace-Id or W3C traceparent when present; otherwise a server-generated UUID v4.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "description": "List connectors.\n\n**Tag:** Bank Connectors\n\nAuthenticate with a bearer token issued by `/v1/oauth/token`. All state-changing requests\n(POST, PUT, PATCH, DELETE) MUST include an `Idempotency-Key` header (UUID v4) to make\nretries safe — Kang will return the original response for any duplicate key within 24 hours.\n\nErrors follow [RFC 7807](https://datatracker.ietf.org/doc/html/rfc7807) and are returned with\n`Content-Type: application/problem+json`. The `code` field is stable and machine-readable.\nRate-limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)\nare present on every response.",
        "x-codeSamples": [
          {
            "lang": "cURL",
            "label": "cURL",
            "source": "curl -X GET \"https://api.kangopenbanking.com/v1/banks/{bankId}/connectors\" \\\n  -H \"Authorization: Bearer $KOB_API_KEY\" \\\n  -H \"X-Request-Id: $(uuidgen)\""
          },
          {
            "lang": "JavaScript",
            "label": "Node.js",
            "source": "import { KangClient } from '@kangopenbanking/sdk';\n\nconst kang = new KangClient({ apiKey: process.env.KOB_API_KEY });\n\nconst response = await kang.request({\n  method: 'GET',\n  path: '/v1/banks/{bankId}/connectors',\n});\n\nconsole.log(response.data);"
          },
          {
            "lang": "Python",
            "label": "Python",
            "source": "from kangopenbanking import Kang\nimport os, uuid\n\nkang = Kang(api_key=os.environ[\"KOB_API_KEY\"])\n\nresponse = kang.request(\n    method=\"GET\",\n    path=\"/v1/banks/{bankId}/connectors\",\n)\n\nprint(response.data)"
          },
          {
            "lang": "PHP",
            "label": "PHP",
            "source": "<?php\nrequire 'vendor/autoload.php';\n\n$kang = new \\KangOpenBanking\\Client(getenv('KOB_API_KEY'));\n\n$response = $kang->request([\n    'method' => 'GET',\n    'path'   => '/v1/banks/{bankId}/connectors',\n]);\n\nprint_r($response->data);"
          }
        ]
      },
      "post": {
        "tags": [
   